

var ATFx = Class.create({
	Version: "1.3.3",
	Required_Prototype: "1.6.0.3",
	Required_Scriptaculous: "1.8.2"
});

ATFx.Links = Class.create({
	Filters: {
		js: new RegExp("^[javascript:]", "i"),
		localAnchor: new RegExp("^[#]", "i"),
		extUrl: new RegExp("^[http://]", "i"),
		extSafe: new RegExp("(.gov)", "i"),
		email: new RegExp("^[mailto:]", "i"),
		protocol: new RegExp("(http://|https://|ftp://)", "i"),
		image: new RegExp("(.jpg|.jpeg|.gif|.png)", "i"),
		govDelivery: new RegExp("(govdelivery.com)", "i")
	},
	Urls: {
		baseSiteUrl: "http://www.atf.gov"
	},
	isExternal: function(href) { 
		return ((href.toString().match(this.Filters.extUrl)) ? true : false); }, // True if link is external
	isPermitted: function(href) { 
		return ((href.toString().match(this.Filters.extSafe)) ? true : false); }, // True if link on safe list
	isJavaScript: function(href) { 
		return ((href.toString().match(this.Filters.js)) ? true : false); }, // True if link begins with "javascript:"
	isEmail: function(href) { 
		return ((href.toString().match(this.Filters.email)) ? true : false); }, // True if link begins with "mailto:"
	isHyperlink: function(href) { 
		return (((href.nodeName.toLowerCase() === "a") && (!href.match(this.Filters.localAnchor))) ? true : false); }, // True if node is anchor
	isImageLink: function(href) {
		return ((href.toString().match(this.Filters.image)) ? true : false); },
	isClickableImage: function(href) {
		return (((href.firstDescendant()) && (href.firstDescendant().nodeName.toLowerCase() === "img")) ? true : false); },
	isGovDelivery: function(href) {
		return ((href.toString().match(this.Filters.govDelivery)) ? true : false); },
	getDomain: function(href) { 
		return ((href.toString().slice(0, href.toString().indexOf("/",8)+1)) || (href+"/")); }, // Returns domain only (omits path)
	getEmailAddress: function(href) { 
		return (href.toString().replace(/mailto:/, "")); }, // Returns email address only
	formatLocalUrl: function(href) {
		return (this.Urls.baseSiteUrl + href); }
});

ATFx.LinkMonitor = Class.create(ATFx.Links, {
	Config: {
		showExitNotice: true, // turn on/off exit notice
		showLightbox: true, // turn on/off lightbox
		showMagnifyIcon: true, // turn on/off magnification icons (adds class and span element)
		extClass: "external", // external link class (used for css ::after)
		extClassImg: "externalImage", // external img class
		magnifyClass: "magnify", // lightbox link class
		nodes: "a" // page elements to gather
	},
	initialize: function(id) {
		this.id = id;
		this.ref = this.gatherReferences();
		this.displayExitNoticeEvent = this.displayExitNotice.bindAsEventListener(this);
		this.displayGovDeliveryEvent = this.displayGovDelivery.bindAsEventListener(this);
		this.displayImageEvent = this.displayImage.bindAsEventListener(this);
		this.ref.each(function(href) { 
			if (this.isGovDelivery(href)) { this.monitorGovDelivery(href); }
			else if (this.Config.showExitNotice && this.needsExternalMonitoring(href)) { this.monitorExternal(href); } 
			else if (this.Config.showLightbox && this.needsLightbox(href)) { this.monitorImage(href); }
		}, this);
	},
	gatherReferences: function() {
		return $(this.id).select(this.Config.nodes);
	},
	needsExternalMonitoring: function(href) {
		return (((this.isExternal(href)) && (!this.isPermitted(href)) && (this.isHyperlink(href))) ? true : false);
	},
	needsLightbox: function(href) {
		return (((this.isClickableImage(href)) && (this.isImageLink(href))) ? true : false);
	},
	monitorExternal: function(href) {
		href.addClassName(this.Config.extClass).observe("click", this.displayExitNoticeEvent);
		if (this.isClickableImage(href)) { href.addClassName(this.Config.extClassImg); }
	},
	monitorGovDelivery: function(href) {
		href.observe("click", this.displayGovDeliveryEvent);
	},
	monitorImage: function(href) {
		if (this.Config.showMagnifyIcon) { href.addClassName(this.Config.magnifyClass).insert(new Element("span")); }
		href.observe("click", this.displayImageEvent);
	},
	displayExitNotice: function(e) {
		var el = ((Event.element(e).nodeName.toLowerCase() === "img") ? Event.element(e).up(0) : Event.element(e));
		if (el.getAttribute("href")) {
			Event.stop(e);
			new ATFx.ModalWindow.ExitNotice({ 
				domain: this.getDomain(el.getAttribute("href")), 
				href: el.getAttribute("href"), 
				ev: e
			});
		}
	},
	displayGovDelivery: function(e) {
		Event.stop(e);
		window.open(Event.element(e).getAttribute("href"),'Popup','width=750,height=440,toolbar=no,scrollbars=yes,resizeable=yes');
	},
	displayImage: function(e) {
		var node = Event.element(e).nodeName.toLowerCase();
		var el = ((node === "img") || (node === "span")) ? Event.element(e).up(0) : Event.element(e);
//		var cap = ;
		if (el.getAttribute("href")) {
			Event.stop(e);
			new ATFx.ModalWindow.Lightbox({ 
				href: el.getAttribute("href"),
				caption: (el.getElementsByTagName("img")[0].getAttribute("alt") || ""),
				ev: e
			});
		}
	}
});

ATFx.QuoteFix = Class.create({
	Config: {
		nodes: "q",
		openDQuote: "&ldquo;",
		closeDQuote: "&rdquo;",
		openSQuote: "&lsquo;",
		closeSQuote: "&rsquo;"
	},
	Filters: {
		quoted: new RegExp("(“|\"|”)", "i"),
		startQuote: new RegExp("^(“|\")", "i"),
		endQuote: new RegExp("(\"|”)$", "i"),
		improperEndQuote: new RegExp("(\"\\W|”\\W)$", "i")
	},
	initialize: function(id) {
		this.id = id;
		this.ref = this.gatherReferences();
		this.removeQuotes();
		if (Prototype.Browser.IE6 || Prototype.Browser.IE7) {
			this.addQuotes();
		}
	},
	gatherReferences: function() {
		return $(this.id).select(this.Config.nodes);
	},
	isQuoted: function(text) {
		return ((text.toString().match(this.Filters.quoted)) ? true : false);
	},
	isPoorGrammar: function(text) {
		return ((text.toString().match(this.Filters.improperEndQuote)) ? true : false);
	},
	removeQuotes: function() {
		this.ref.each(function(el) {
			if (this.isPoorGrammar(el.innerHTML)) {
				var t = el.innerHTML.toString();
				el.update(t.substr(0,t.length-2)+t.substr(t.length-1));
			}
			if (this.isQuoted(el.innerHTML)) {
				el.update(el.innerHTML.toString().replace(this.Filters.startQuote, ""));
				el.update(el.innerHTML.toString().replace(this.Filters.endQuote, ""));
			}
		}, this);
	},
	addQuotes: function() {
		this.ref.each(function(el) {
			if (el.up(0).nodeName.toLowerCase() === "q") { el.insert({ before: this.Config.openSQuote, after: this.Config.closeSQuote }); }
			else { el.insert({ before: this.Config.openDQuote, after: this.Config.closeDQuote }); }
		}, this);
	}
});

ATFx.Form = Class.create({
	initialize: function() {
	}
});

ATFx.Form.Help = Class.create(ATFx.Form, {
	Config: {
		nodes: "em.help",
		linkClassName: "help",
		helpText: "Help: "
	},
	initialize: function(id) {
		this.id = id;
		this.ref = this.gatherReferences();
		this.createHelp();
	},
	gatherReferences: function() {
		return $(this.id).select(this.Config.nodes);
	},
	createHelp: function() {
		this.showHelpEvent = this.showHelp.bindAsEventListener(this);
		this.ref.each(function(el) {
			el.hide().up(0).insert(
				new Element("a", { href: "javascript:void(0);", className: this.Config.linkClassName }).update(this.Config.helpText + el.innerHTML).observe("click", this.showHelpEvent)
			);
		}, this);
	},
	showHelp: function(e) {
		new ATFx.ModalWindow.Mini({
			text: Event.element(e).up(0).select(this.Config.nodes)[0].innerHTML,
			ev: e
		});
	}
});

ATFx.Overlay = Class.create({
	overlayID: "overlay",
	initialize: function() {
		if (!$(this.overlayID)) { this.createOverlay(); }
		this.monitorOverlay();
	},
	createOverlay: function() {
		var div = new Element("div", { id: "overlay" }).hide();
		div.style.height = Element.getHeight($$("body")[0]);
		$$("body")[0].insert(div);
		new Effect.Appear(div, { from: 0.4, to: 0.4, duration: 0.0 });
	},
	monitorOverlay: function() {
		Event.observe(document, 'keypress', (function(e) { if(e.keyCode === Event.KEY_ESC) { this.removeOverlay(); } }).bind(this));
		$(this.overlayID).observe("click", (function() { this.removeOverlay(); }).bind(this));
	},
	removeOverlay: function() {
		Event.stopObserving(document, "keypress", (function(e) { if(e.keyCode === Event.KEY_ESC) { this.removeOverlay(); } }).bind(this));
		$(this.overlayID).stopObserving("click", (function() { this.removeOverlay(); }).bind(this));
		$(this.overlayID).remove();
	}
});

ATFx.ModalWindow = Class.create(ATFx.Overlay, {
	Config: {
		modalID: "modalWindow",
		modalClassBase: "modal",
		modalAccessLinkID: "modalAccess",
		modalCloseLinkClass: "modalClose",
		modalCloseLinkTitle: "Notice: This dialog box may require a response from the user. Select this link to close dialog box and cancel the performed action to return to the document.",
		modalDefaultTop: 100
	},
	getScrollTop: function() {
		return ((window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop)  + this.Config.modalDefaultTop + "px");
	},
	createModalBase: function() {
		if (!$(this.overlayID)) { this.createOverlay(); }
		this.createModalBaseWindow();
	},
	createModalBaseWindow: function() {
		if ($(this.Config.modalID)) { $(this.Config.modalID).remove(); }
		this.modal = new Element("div", { id: this.Config.modalID, className: this.type, style: "top: " + this.getScrollTop() }).insert(
			new Element("div", { className: this.Config.modalCloseLinkClass }).insert(
				new Element("a", { href: "javascript:void(0);", name: this.Config.modalAccessLinkID, id: this.Config.modalAccessLinkID, title: this.Config.modalCloseLinkTitle }).update("Close")).insert(
				new Element("span").update("or <kbd>ESC</kbd>"))
		);
	},
	monitorModalWindowDefaults: function() {
		this.keyPressDefaultEvent = this.onKeyPressDefault.bindAsEventListener(this);
		this.onCloseDefaultEvent = this.onCloseDefault.bindAsEventListener(this);
		Event.observe(document, 'keypress', this.keyPressDefaultEvent);
		$(this.Config.modalAccessLinkID).observe("click", this.onCloseDefaultEvent);
		if ($(this.overlayID)) { $(this.overlayID).observe("click", this.onCloseDefaultEvent); }
	},
	onKeyPressDefault: function(e) {
		if(e.keyCode === Event.KEY_ESC) { this.removeModalWindow(); }
	},
	onCloseDefault: function(e) {
		this.removeModalWindow();
	},
	insertModalWindow: function() {
		$$("body")[0].insert(this.modal);
		new Effect.Appear(this.Config.modalID);
		$(this.Config.modalAccessLinkID).focus();
	},
	removeModalWindow: function() {
		this.afterFinishEvent = this.afterFinish.bindAsEventListener(this);
		new Effect.DropOut(this.Config.modalID, { afterFinish: this.afterFinishEvent });
	},
	afterFinish: function() {
		Event.stopObserving(document, "keypress", this.keyPressDefaultEvent);
		$(this.Config.modalAccessLinkID).stopObserving("click", this.onCloseDefaultEvent);
		if ($(this.Config.modalID)) { $(this.Config.modalID).remove(); }
		if ($(this.overlayID)) { 
			$(this.overlayID).stopObserving("click", this.onCloseDefaultEvent);
			$(this.overlayID).remove();
		}
		this.returnFocus();
	},
	returnFocus: function() {
		Event.element(this.ev).focus();
	}
});

ATFx.ModalWindow.ExitNotice = Class.create(ATFx.ModalWindow, {
	ExtendedConfig: {
		type: "ExitNotice",
		header: "Exit Notice",
		content: "<p>You are now leaving the ATF public web server and are going to a web site that ATF does not control whose privacy policies may differ.</p><p>Thank you for visiting our site.</p><p class=\"externalSite\">You can access ::site:: by choosing &lsquo;Continue;&rsquo; otherwise choose &lsquo;Cancel.&rsquo;</p><p>We hope your visit was informative and enjoyable.</p>"
	},
	initialize: function(args) {
		this.args = args;
		this.domain = this.args.domain;
		this.href = this.args.href;
		this.type = ((this.Config.modalClassBase + this.ExtendedConfig.type) || (this.Config.modalClassBase));
		this.content = this.ExtendedConfig.content.replace(/::site::/, "<a href=\"" + this.href + "\">" + this.domain + "</a>");
		this.ev = this.args.ev;
		this.createModalWindow();
	},
	createModalWindow: function() {
		this.createModalBase();
		this.insertModalContent();
		this.insertModalWindow();
		this.monitorModalWindowDefaults();
	},
	insertModalContent: function() {
		this.cancelExitEvent = this.cancelExit.bindAsEventListener(this);
		this.allowExitEvent = this.allowExit.bindAsEventListener(this);
		this.modal.insert(
			new Element("h1").update(this.ExtendedConfig.header)).insert(
			new Element("div").update(this.content)).insert(
			new Element("button").update("Continue").observe("click", this.allowExitEvent)).insert(
			new Element("button").update("Cancel").observe("click", this.cancelExitEvent)
		);
	},
	cancelExit: function(e) {
		Event.element(e).stopObserving("click", this.cancelExitEvent);
		this.removeModalWindow();
	},
	allowExit: function() {
		window.location = this.href;
	}
});

ATFx.ModalWindow.Lightbox = Class.create(ATFx.ModalWindow, {
	ExtendedConfig: {
		imgID: "enlargedImage",
		type: "Lightbox",
		paddingTop: 50, // Approximate height of default close
		morphDuration: 0.8 // In seconds
	},
	initialize: function(args) {
		this.args = args;
		this.type = ((this.Config.modalClassBase + this.ExtendedConfig.type) || (this.Config.modalClassBase));
		this.href = this.args.href;
		this.ev = this.args.ev;
		this.createModalWindow();
	},
	createModalWindow: function() {
		this.createModalBase();
		this.insertModalWindow();
		this.monitorModalWindowDefaults();
		this.insertModalContent();
	},
	insertModalContent: function() {
		var img = new Image();
		img.onload = (function(){ this.imageLoaded(img); }).bind(this);
		img.src = this.href;
	},
	imageLoaded: function(img) {
		this.showImageEvent = this.showImage.bindAsEventListener(this);
		this.modal.insert(new Element("img", { src: img.src, id: this.ExtendedConfig.imgID }).hide());
		new Effect.Morph(this.Config.modalID, { 
			style: "height: " + (img.height+this.ExtendedConfig.paddingTop) + "px; " + 
				   "width: " + (img.width) + "px; " +
				   "margin-left: -" + (img.width/2) + "px; ",
			duration: this.ExtendedConfig.morphDuration,
			afterFinish: (this.showImageEvent)
		});
	},
	showImage: function() {
		$(this.ExtendedConfig.imgID).show();
		if (this.args.caption != "") {
			this.modal.insert(new Element("p", { className: "caption" }).update(this.args.caption));
			this.modal.getElementsByTagName("p")[0].style.width = this.modal.getElementsByTagName("img")[0].width + "px"
		}
	}
});

ATFx.ModalWindow.Mini = Class.create(ATFx.ModalWindow, {
	ExtendedConfig: {
		type: "Mini",
		header: "Help",
		marginLeft: "20px",
		marginTop: "-30px"
	},
	initialize: function(args) {
		this.args = args;
		this.type = ((this.Config.modalClassBase + this.ExtendedConfig.type) || (this.Config.modalClassBase));
		this.ev = this.args.ev;
		this.createModalWindow();
	},
	createModalWindow: function() {
		this.createModalBaseWindow();
		this.positionModalWindow();
		this.insertModalWindow();
		this.monitorModalWindowDefaults();
		this.insertModalContent();
	},
	positionModalWindow: function() {
		this.modal.style.left = Event.element(this.ev).cumulativeOffset()[0] + "px";
		this.modal.style.top = Event.element(this.ev).cumulativeOffset()[1] + "px";
		this.modal.style.marginLeft = this.ExtendedConfig.marginLeft;
		this.modal.style.marginTop = this.ExtendedConfig.marginTop;
	},
	insertModalContent: function() {
		this.modal.insert( new Element("p").update(this.args.text) );
	}
});

ATFx.FlyoutMenu = Class.create({
	initialize: function(id) {
		$(id).select("ul.subMenu").each(function(el) {
			Event.observe(el.up(0), "mouseover", function() { this.addClassName("hover"); });
			Event.observe(el.up(0), "mouseout", function() { this.removeClassName("hover"); });
		}, this);
		var li = $(id).select("li");
		this.showEvent = this.show.bindAsEventListener(this);
		this.hideEvent = this.hide.bindAsEventListener(this);
		for (var i = 0; i < li.length; i++) {
			Event.observe(li[i].down(0), "focus", this.showEvent);
			Event.observe(li[i].down(0), "blur", this.hideEvent);
		}
		$(id).select("ul.noScript")[0].className = "script";
	},
	show: function(e) {
		el = Event.element(e).up(0);
		this.bubble(el, "add");
	},
	hide: function(e) {
		el = Event.element(e).up(0);
		this.bubble(el, "remove");
	},
	bubble: function(el,c) {
		if (c === "add") { while (el.nodeName.toLowerCase() === "li") { el.addClassName("hover"); el = el.up(1); } }
		else { while (el.nodeName.toLowerCase() === "li") { el.removeClassName("hover"); el = el.up(1); } }
	}
});

ATFx.FollowLinks = Class.create({
	Config: {
		popID: "followPopup"
	},
	initialize: function(id) {
		this.id = id;
		var links = $(this.id).select("a");
		this.showEvent = this.show.bindAsEventListener(this);
		this.hideEvent = this.hide.bindAsEventListener(this);
		links.each(function(el) {
			Event.observe(el, "mouseover", this.showEvent);
			Event.observe(el, "mouseout", this.hideEvent);
			Event.observe(el, "focus", this.showEvent);
			Event.observe(el, "blur", this.hideEvent);
		}, this);
	},
	show: function(e) {
		el = Event.element(e);
		$(this.id).up(0).insert(new Element("div", { id: this.Config.popID }).update(el.innerHTML));
	},
	hide: function(e) {
		$(this.Config.popID).remove();
	}
});

ATFx.FeaturedStories = Class.create({
	period:  5,
	executor: "",
	cName: "div.featuredStory",
	navID: "storyNumbers",
	currentStory: "currentStory",
	nextStory: "nextStory",
	initialize: function(id) {
		this.id = id;
		$(this.id).addClassName("featuredStoriesScripted");
		this.stories = $(this.id).getElementsBySelector(this.cName);
		this.stories.each(function(el) { el.hide(); });
		if (this.stories.length > 1) { this.createNav(); }
		this.setCurrent($$(this.cName)[0]);
		this.cycleEvent = this.cycle.bindAsEventListener(this);
		if ($$(this.cName).length > 1) { 
			this.setNext($$(this.cName)[1]);
			this.executor = new PeriodicalExecuter(this.cycleEvent, this.period);
		}
	},
	createNav: function() {
		var ol = new Element("ol", { id: this.navID });
		var i = 1;
		this.jumpToStoryEvent = this.jumpToStory.bindAsEventListener(this);
		this.stories.each(function(el) {
			ol.insert(new Element("li").insert(new Element("a", { href: "javascript:void(0)" }).update(i).observe("click", this.jumpToStoryEvent)));
			i++;
		}, this);
		$(this.id).insert(ol);
		$(this.navID).down(0).className = "current";
	},
	updateNav: function() {
		for (var i = 0; i < this.stories.length; i++) {
			$(this.navID).getElementsBySelector("li")[i].className = "";
			if (this.stories[i].getAttribute("id") === this.nextStory) {
				$(this.navID).getElementsBySelector("li")[i].className = "current";
			}
		}
	},
	jumpToStory: function(e) {
		var i = Event.element(e).innerHTML;
		this.executor.stop();
		if (this.effect) { this.effect.cancel(); }
		$(this.nextStory).hide();
		$(this.nextStory).removeAttribute("id");
		this.setNext(this.stories[parseInt(i)-1]);
		new Effect.Opacity(this.nextStory, { to: 1 });
		this.cycle();
	},
	setCurrent: function(el) {
		el.setAttribute("id",this.currentStory);
		el.show();
	},
	setNext: function(el) {
		el.setAttribute("id",this.nextStory);
		el.show();
	},
	cycle: function() {
		this.updateNav();
		this.effect = new Effect.Fade(this.currentStory, { duration: 1.0, from: 1, to: 0, afterFinish: this.afterFinish.bindAsEventListener(this) });
	},
	afterFinish: function() {
		new Effect.Opacity(this.currentStory, { to: 1 });
		$(this.currentStory).removeAttribute("id");
		this.setCurrent($(this.nextStory));
		if (($(this.currentStory).next(0)) && ($(this.currentStory).next(0).nodeName.toLowerCase() === "div")) { this.setNext($(this.currentStory).next(0)); }
		else { this.setNext(this.stories[0]); }
	}
});

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) === 6;
Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) === 7;
Prototype.Browser.IE8 = Prototype.Browser.IE && !Prototype.Browser.IE6 && !Prototype.Browser.IE7; 


