﻿// used by glossarysupport.js and WrapBigTablesInScrollable()
Prototype.Browser.IE6 = function() {
  if( Prototype.Browser.IE ) {
    var ua      = navigator.userAgent;
    var offset  = ua.indexOf('MSIE ');
    var version = parseFloat(ua.substring(offset+5, ua.indexOf(';', offset)));
    return version == 6;
  }
  return false;
}

function Print()
{
	window.print();
}

function SideTabWasOpen()
{
	// TODO: implement state via cookies
	return false;
}

// side tab expand/collapse script
function ToggleSideTab2()
{
	var sidetab = $("sideTab2Toggle");
	if (sidetab.hasClassName("expanded"))
	{
		sidetab.removeClassName("expanded");
		sidetab.addClassName("collapsed");
		Effect.BlindUp('sideTab2Contents', { duration: 0.6 });
	}
	else
	{
		sidetab.removeClassName("collapsed");
		sidetab.addClassName("expanded");
		// have to tell it the original dimensions, so it will work when the animation is interrupted by the user
		// have to override afterFinishInternal -- b/c if you start BlindDown before BlindUp is finished, BlindDown's afterFinishInternal (which undoes the clipping) runs *after* BlindUp's introductory code (which makes the clipping)
		Effect.BlindDown('sideTab2Contents', { duration: 0.6, scaleMode: {originalHeight: objOriginalDimensions.height, originalWidth: objOriginalDimensions.width }, afterFinishInternal: function() { } });
	}
}

function ShowDisclaimer(event)
{ 

 var elemLink = Event.findElement(event, "a");
 if (elemLink && elemLink.href)
 {
   var reURL = new RegExp("[a-z]+://([^/]+)", "i");
   var aLocationResult = window.location.href.match(reURL);
   var aLinkResult = elemLink.href.match(reURL);
   if (aLocationResult && aLinkResult && aLocationResult[1] != aLinkResult[1])
   { 
     // we have an offsite link, now check if it is NOT .dot.gov
     if (aLinkResult[1].match(".dot.gov$")==null)
       if (aLinkResult[1] != "service.govdelivery.com")
         alert("Links to web sites outside of the Department of Transportation (DOT) are offered for your convenience in accessing related information. Please be aware that when you exit The Office of Pipeline Safety (OPS) web site, the privacy policy stated on our web site may NOT be the same as that on other web sites. OPS takes no responsibility for and exercises no control over the organization, views, or accuracy of the information contained on their servers.");
   }
 }
}
// A simple URL parser based on the RFC's BNF (http://www.faqs.org/rfcs/rfc1738.html) and pyparser
function parseHttpURL(strURL) {
	// pyparser fundamentals
	var alphas = "a-zA-Z";
	var nums = "0-9";
	var alphanums = alphas + nums;
	var hexnums = nums + "A-Fa-f";
	
	// URL BNF "misc definitions"
	var safe = esc("$") + esc("-") + "_" + esc(".") + esc("+");
	var extra = esc("!") + esc("*") + "'" + esc("(") + esc(")") + ",";
	var unreserved = alphanums + safe + extra;
	var escape = "%"; //+ hexnums + hexnums; // we have to deal with hex differently, in keeping with pyparsing syntax instead of BNF
	var uchar = unreserved + escape;
	var digits = Word(nums);
	
	// general URL rules
	var port = digits;
	var hostnumber = digits + esc(".") + digits + esc(".") + digits + esc(".") + digits;
	var toplabel = Word(alphanums + "-"); // alpha | alpha *[ alphadigit | "-" ] alphadigit;
	var domainlabel = Word(alphanums + "-"); // alphadigit | alphadigit *[ alphadigit | "-" ] alphadigit;
	var hostname = ZeroOrMore(domainlabel + esc(".")) + toplabel;
	var host = NonCaptureGroup(hostname + "|" + hostnumber);
	var hostport = Group(host) + Optional(":" + port);
	
	// HTTP-specific rules
	var search = Optional(Word(uchar + ";:@&="));
	var hsegment = Optional(Word(uchar + ";:@&="));
	var hpath = hsegment + ZeroOrMore("/" + hsegment);
	var httpurl = Group("https?") + "://" + hostport + Group(Optional("/" + hpath + Optional(Group(esc("?") + search))));
	
	// the RFC doesn't specify this, but does allude to it in section 2.2 under "Unsafe" in the sentence about "#".
	var anchor = Optional(Word(uchar + ";:@&="));
	var httpfullurl = httpurl + Group(Optional("#" + anchor));
	
	// parse it & return the results as an object
	var results = parseString(httpfullurl, strURL);
	if (!results) return null;
	
	var strQuery = results[4] ? results[4] : ""; //(results.length == 6) ? results[4] : "";
	var strPath = results[3].substr(1, results[3].length - strQuery.length - 1); // subtract 1 for "/"
	if (strQuery != "") strQuery = strQuery.substr(1); // strip the beginning "?" -- but *after* strPath removes it b/c of the length
	var strHash = results[results.length - 1].substr(1);
	return { protocol: results[1], host: results[2], path: strPath, query: strQuery, hash: strHash };
	
	// tests
	/*var results = [];
	results.push(testParse(digits, "123"), testParse(digits, "1"), testNoParse(digits, ""), testNoParse(digits, "abc"));
	results.push(testParse(Word(uchar), "test%36.("), testNoParse(Word(alphanums), "test://"));
	results.push(testParse(hostnumber, "128.0.0.1"), testNoParse(hostnumber, "www.google.com"));
	results.push(testParse(hostname, "www.google.com"));
	results.push(testParse(hostport, "128.0.0.1:8080"), testParse(hostport, "www.google.com:80"), testParse(hostport, "www.google.com"));
	results.push(testParse(httpurl, "http://www.google.com"));
	results.push(testParse(httpurl, "http://www.google.com/hosted/index/csnw.org?test=true&test2=false"));
	results.push(testNoParse(httpurl, "http://www.google.com/hosted/index/csnw.org?test=true&test2=false#myanchor"));
	results.push(testParse(httpfullurl, "http://www.google.com/hosted/index/csnw.org?test=true&test2=false#myanchor"));
	alert(results.join("\n"));*/
}

function parseString(strPattern, str) { 
	return new RegExp("^" + strPattern + "$").exec(str);
}
function testParse(strPattern, str) {
	if (parseString(strPattern, str))
		return "Passed: " + str;
	else
		return "Failed: " + str;
}
function testNoParse(strPattern, str) {
	if (parseString(strPattern, str))
		return "Failed: " + str;
	else
		return "Passed: " + str;
}

// write a function that returns a regex, given the supplied strings
// write a series of asserts that start with the simplest and work up to the biggest, including pass & fail asserts
function Word(allowedChars) {
	return "[" + allowedChars + "]+";
}
function Optional(str) {
	return NonCaptureGroup(str) + "?";
}
function OneOrMore(str) { 
	return NonCaptureGroup(str) + "+";
}
function ZeroOrMore(str) {
	return NonCaptureGroup(str) + "*";
}
function NonCaptureGroup(str) {
	return "(?:" + str + ")";
}
function Group(str) {
	return "(" + str + ")";
}
// performs a reg-ex escape
function esc(character) {
	return "\\" + character;
}
function ImplementCacheBusting() {
	var aErrors = [];
	$$("a").each(function(elem) {
		var URL = parseHttpURL(elem.href);
		if (URL) {
			var currentURL = parseHttpURL(window.location.href);
			if (currentURL) {
				// ignore anchor links (links w/ same base url)
				if (IsSameSite(currentURL, URL) && !IsSamePage(currentURL, URL))
					elem.href = InjectCacheBuster(URL);
			}
			else aErrors.push("!! " + window.location.href);
		}
		else aErrors.push("!! " + elem.href);
	});
}

function IsSamePage(currentURL, URL) {
	return currentURL.protocol == URL.protocol && currentURL.host == URL.host && currentURL.path == URL.path && currentURL.query == URL.query;
}
function IsSameSite(currentURL, URL) {
	return currentURL.protocol == URL.protocol && currentURL.host == URL.host;
}

function InjectCacheBuster(URL) {
	URL.query = URL.query + (URL.query ? '&' : '') + "nocache=" + Math.ceil(10000 * Math.random());
	return URL.protocol + "://" + URL.host + "/" + URL.path + "?" + URL.query + (URL.hash ? '#' : '') + URL.hash;
}

function AddImageCaptions() {
	$$('img.caption').each(function(img) {
		if (img.alt) {
			img = $(img);
			var captionContainer = document.createElement("div");
			img.parentNode.replaceChild(captionContainer, img);
			captionContainer.appendChild(img);
			var caption = document.createElement("div");
			captionContainer.appendChild(caption);
			captionContainer.className = "caption-container";
			caption.innerHTML = img.alt;
			caption.className = "caption";
			["in-text-right", "in-text-left"].each(function(strClassName) {
				if (img.hasClassName(strClassName)) {
					img.removeClassName(strClassName);
					captionContainer.className += " " + strClassName;
				}
			});
			// I don't believe this is possible to do in CSS
			// (to get the container to shrink to the image-width when the caption text is wider)
			captionContainer.style.width = img.getWidth() + 'px';
		}
	});
}

function SelectCurrentState(event)
{
	var aURLParts = window.location.href.split("/");
	if (aURLParts.length > 0)
	{
		var strLastURLPart = aURLParts[aURLParts.length - 1];
		var selStates = $("selStates");
		if (selStates)
		{
			var aOptions = $A(selStates.options);
			aOptions.each(function(elOption, nIndex) 
			{
				if (elOption.value && strLastURLPart.startsWith(elOption.value)) selStates.selectedIndex = nIndex;
			});
		}
	}
}

// partial port from Prototype 1.6, remove & use "document.viewport" when upgraded to 1.6
var documentViewport = {
  getDimensions: function() {
    var dimensions = { };
    var B = Prototype.Browser;
    $w('width height').each(function(d) {
      var D = d.capitalize();
      dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
        (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
    });
    return dimensions;
  }
};

// copied from Prototype 1.6, remove & use "Element.wrap" when upgraded to 1.6
function wrapElement(element, wrapper, attributes) {
    element = $(element);
    if (Object.isElement(wrapper))
      $(wrapper).writeAttribute(attributes || { });
    else if (Object.isString(wrapper)) {
    	var wrapper = document.createElement(wrapper);
    	for(strKey in attributes)
			wrapper.setAttribute(strKey, attributes[strKey]);
    	//wrapper = new Element(wrapper, attributes); Prototype 1.6 only
    }
    else wrapper = new Element('div', wrapper);
    if (element.parentNode)
      element.parentNode.replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return $(wrapper);
}
Object.isElement = function(object) { return object && object.nodeType == 1; };
Object.isString = function(object) { return typeof object == "string"; };

// sum up all ancestor paddings - move to PreviewOswego to test this
function WrapBigTablesInScrollable() {
	var contentSpace = documentViewport.getDimensions().width - $('divSide').getWidth() - 55; // 25px padding?
	$$('table').each(function(table) {
		if (table.getWidth() > contentSpace) {
			
			// get cumulative padding
			var cumulativePadding = 50;
			var ancestors = table.ancestors();
			var ancestor_ids = ancestors.pluck('id');
			var divContentBody_num = ancestor_ids.indexOf('divContentBody');
			ancestors = ancestors.slice(0, divContentBody_num);
			cumulativePadding += GetCumulativeHorizontalPadding(ancestors);
			
			// if the cells in the 'filler' column are extending (too far), just reset the table width (no need to wrap w/ scrollable div)
			var fillers = table.select('td.filler');
			if (fillers.length && fillers[0].getWidth() > (20 + cumulativePadding)) {
				table.style.width = (contentSpace - cumulativePadding) + 'px';
			}
			else {
				var wrapper;
				if (table.parentNode.style.overflow == 'scroll')
					wrapper = $(table.parentNode);
				else
					wrapper = wrapElement(table, 'div');

				wrapper.style.width = (contentSpace - cumulativePadding) + 'px';
				wrapper.style.overflow = 'scroll';
			}
		}
	});
}

// sum all padding into accumulator
function GetCumulativeHorizontalPadding(ancestors) {
	return ancestors.inject(0, function(acc, elem) {
		return acc + getPix(elem.getStyle('padding-left')) + getPix(elem.getStyle('padding-right')) + getPix(elem.getStyle('margin-left')) + getPix(elem.getStyle('margin-right'));
	});
}

function getPix(strPix) {
	if (!strPix) return 0;
	if (strPix.endsWith('px'))
		return parseInt(strPix.substr(0, strPix.length - 'px'.length), 10);
	 // OK: it's SUPER TOUGH to figure out how many pixels are in an 'em', maybe we shouldn't pretend we know?
	if (strPix.endsWith('em'))
		return parseFloat(strPix.substr(0, strPix.length - 'em'.length), 10) * 10;
	return 0;
}

if (Prototype.Browser.IE6())
	Event.observe(window, "resize", WrapBigTablesInScrollable);

// TODO: move this to 'dom:loaded' once we upgrade to Prototype 1.6
Event.observe(window, 'load', function() {
	Event.observe('divContentBody', 'click', ShowDisclaimer);
	ImplementCacheBusting();
	AddImageCaptions();
	if (Prototype.Browser.IE6())
		WrapBigTablesInScrollable();
});

if (Prototype.Browser.Gecko)
	Event.observe(window, "pageshow", SelectCurrentState);
else
	Event.observe(window, "load", SelectCurrentState);