if (typeof(AC) == "undefined") { AC = {}; }AC.Bureau = Class.create();Object.extend(AC.Bureau.prototype, Event.Listener);Object.extend(AC.Bureau.prototype, {		drawers: null,	container: null,		triggerTimeout: null,		initialize: function(container) {		this.drawers = [];		this.container = $(container);	},		addDrawer: function(newDrawer) {},		getDrawerCount: function() {		return this.drawers.length;	},		hasDrawers: function() {		return (this.drawers.length > 0);	},		getFirstDrawer: function() {		return this.drawers[0] || null;	},		getLastDrawer: function() {		return this.drawers[this.drawers.length-1] || null;	},		scheduleTrigger: function(onFire, delay) {		this.triggerTimeout = setTimeout(onFire, delay);	},		clearTrigger: function() {		clearTimeout(this.triggerTimeout);	}});AC.Drawer = Class.create();Object.extend(AC.Drawer.prototype, Event.Publisher);Object.extend(AC.Drawer.prototype, {		bureau: null,		contentElement: null,	handle: null,	indicator: null,		isOpen: true,		beforeOpen: null,	afterOpen: null,		beforeClose: null,	afterClose: null,		transitionDuration: 0.3,	triggerDelay: 0,		//TODO I'd love to not to have thid circular association where the drawers need to know about the bureau and vice versa	//already in some of the newer code like sliderdrawers this dependency has been negated by the use of the event mixins	//the bureau simply observes its drawers for any changes	//might need to see if this is true for all drawer/bureau classes	initialize: function(contentElement, handleElement, bureau, options) {				this.contentElement = contentElement;		this.handle = handleElement;		this.bureau = bureau;				var triggerEvent = 'click';				if(options != null && typeof(options) != 'undefined') {			this.beforeOpen = options.beforeOpen;			this.afterOpen = options.afterOpen;			this.beforeClose = options.beforeClose;			this.afterClose = options.afterClose;						//preserve defaults, but override as necessary			if (typeof(options.triggerEvent) != 'undefined') {				triggerEvent = options.triggerEvent;			}						if(typeof(options.triggerDelay) != 'undefined') {				this.triggerDelay = options.triggerDelay;			}						if(typeof(options.transitionDuration) != 'undefined') {				this.transitionDuration = options.transitionDuration;			}		}				Element.addClassName(this.contentElement, 'last');				var fireTrigger = function(evt) {						Event.stop(evt);						if(this.triggerDelay > 0) {				var onFire = this.trigger.bind(this);				bureau.scheduleTrigger(onFire, this.triggerDelay);			} else {				this.trigger();			}		}				Event.observe(this.handle, triggerEvent, fireTrigger.bind(this), false);		Event.observe(this.handle, 'mouseout', bureau.clearTrigger.bind(bureau), false);			},		toggle: function() {},		open: function() {},		close: function() {}	});AC.SlidingBureau = Class.create();Object.extend(AC.SlidingBureau.prototype, AC.Bureau.prototype);Object.extend(AC.SlidingBureau.prototype, {		isLocked: false,		addDrawer: function(newDrawer) {				Element.addClassName(newDrawer.contentElement, 'last');		Element.addClassName(newDrawer.handle, 'last');				if(this.hasDrawers()) {						var lastDrawer = this.getLastDrawer();						lastDrawer.setNextDrawer(newDrawer);			newDrawer.setPreviousDrawer(lastDrawer);		} else {			Element.addClassName(newDrawer.contentElement, 'first');			Element.addClassName(newDrawer.handle, 'first');		}				this.listenForEvent(newDrawer, 'beforeOpen', false, function(evt) {			var drawer = evt.event_data.data;			this.open(drawer);		});				this.listenForEvent(newDrawer, 'afterOpen', false, function(evt) {			var drawer = evt.event_data.data;			this.acknowledgeOpened(drawer);		});				this.listenForEvent(newDrawer, 'beforeClose', false, function(evt) {			var drawer = evt.event_data.data;			this.close(drawer);		});				this.listenForEvent(newDrawer, 'afterClose', false, function(evt) {			var drawer = evt.event_data.data;			this.acknowledgeClosed(drawer);		});				//TODO may want to change how this is done but we need a way to 		//keep one drawer open initially		if (!Element.hasClassName(newDrawer.contentElement, 'open')) {			newDrawer.initiateClose();		} else {			this.currentDrawer = newDrawer;		}				this.drawers.push(newDrawer);	},		open: function(drawer) {				if(this.isLocked){			return;		}				this.isLocked = true;		//lock size of container to prevent shifting, but only if the 		//implementation of the container is expecting that				//TODO I'd love to do this with an Effect.Parallel of the open and 		//close without all this drawer wedging during the animation but		//I like others had issues in various browsers with that approach		//http://wiki.script.aculo.us/scriptaculous/show/accordion+feature		if (Element.getStyle(this.container, 'position') == 'relative') {						var dimensions = Element.getDimensions(this.container);			Element.setStyle(this.container, {height: dimensions.height + "px"});					this.wedgeDrawersAfter(drawer);						//we want to preserve the minheight specified on the drawers			//because in these cases that's what is specified to size the 			//drawers to whatever particular design somebody cooked up			//but we can't have a minimum height specified during the 			//animation or the animation never actually appears			var minHeight = Element.getStyle(drawer.contentElement, 'min-height');						if (minHeight) {				Element.setStyle(drawer.contentElement, {					'min-height': '0px', //clear the minimum height restriction					height: minHeight}) //set the desired height of the element			}		}						if (this.currentDrawer) {			this.currentDrawer.initiateClose();		}				drawer.open(minHeight);	},		acknowledgeOpened: function(drawer) {		this.currentDrawer = drawer;				if (Element.getStyle(this.container, 'position') == 'relative') {			if (!AC.Detector.isIEStrict()) {				Element.setStyle(this.container, {height: "auto"});			}			this.unwedgeDrawers();		}				this.isLocked = false;	},		close: function(drawer) {				if (Element.getStyle(this.container, 'position') == 'relative') {				var minHeight = Element.getStyle(drawer.contentElement, 'min-height');								if(minHeight) {					Element.setStyle(drawer.contentElement, {						height: minHeight, //lock in the starting height						'min-height': '0px'}); //remove minimum height restriction				}		}				drawer.close(minHeight);	},		acknowledgeClosed: function(drawer) {		if(drawer == this.currentDrawer) {			this.currentDrawer = null;		}	},		wedgeDrawersAfter: function(drawerBeingOpened) {		var wedgeDrawer = function(drawer, offset) {			Element.setStyle(drawer.handle, {				position: 'absolute',				bottom: offset + 'px'})		}				var drawer = this.getLastDrawer();		var offset = 0;				while (drawer!= this.currentDrawer && drawer != drawerBeingOpened) {			wedgeDrawer(drawer, offset);			offset += drawer.handle.getHeight();			drawer = drawer.previousDrawer;		}			},		unwedgeDrawers: function() {		for (var i = this.drawers.length - 1; i >= 0; i--){			Element.setStyle(this.drawers[i].handle, {				position: 'static'})		};	}	});AC.SlidingDrawer = Class.create();Object.extend(AC.SlidingDrawer.prototype, AC.Drawer.prototype);Object.extend(AC.SlidingDrawer.prototype, {		isOpen: true,	isTransitioning: false,		setNextDrawer: function(drawer) {		this.nextDrawer = drawer;		Element.removeClassName(this.contentElement, 'last');		Element.removeClassName(this.handle, 'last');	},		setPreviousDrawer: function(drawer) {		this.previousDrawer = drawer;	},		trigger: function() {		this.toggle();	},		toggle: function() {				if(!this.isOpen) {			this.initiateOpen();		}			},		initiateOpen: function() {				if (this.isTransitioning || this.isOpen) {			return;		}				this.dispatchEvent('beforeOpen', this);			},		open: function(minHeight) {				this.isTransitioning = true;				//need to do this before effect starts so content is visible		Element.addClassName(this.contentElement, 'open');		Element.addClassName(this.handle, 'open');				new Effect.BlindDown(this.contentElement, {			duration: this.transitionDuration,			afterFinish: function() {				this.isOpen = true;				if (minHeight) {					Element.setStyle(this.contentElement, {'min-height': minHeight});					if (!AC.Detector.isIEStrict()) {						Element.setStyle(this.contentElement, {'height': 'auto'});					}				}				this.dispatchEvent('afterOpen', this);				this.isTransitioning = false;			}.bind(this) });	},		initiateClose: function(force) {				if (this.isTransitioning || !this.isOpen) {			return;		}				this.dispatchEvent('beforeClose', this);	},		close: function(minHeight) {				this.isTransitioning = true;				new Effect.BlindUp(this.contentElement, {			duration: this.transitionDuration,			afterFinish: function() {				this.isOpen = false;				Element.removeClassName(this.contentElement, 'open');				Element.removeClassName(this.handle, 'open');				if(minHeight) {					Element.setStyle(this.contentElement, {'min-height': minHeight});					if (!AC.Detector.isIEStrict()) {						Element.setStyle(this.contentElement, {'height': 'auto'});					}				}				this.dispatchEvent('afterClose', this);				this.isTransitioning = false;			}.bind(this) });	}		});/** * Overlapping Shingles * Many sections open, only one visible at a time */AC.ShingleBureau = Class.create();Object.extend(Object.extend(AC.ShingleBureau.prototype, AC.Bureau.prototype), {		drawerDuration: 0.5,		addDrawer: function(newDrawer) {				//establish relationships between drawers		if(this.hasDrawers()) {						var lastDrawer = this.getLastDrawer();						lastDrawer.setNextDrawer(newDrawer);			newDrawer.setPreviousDrawer(lastDrawer);			newDrawer.closedOffset = lastDrawer.closedOffset + lastDrawer.getHandleHeight() - 10;		} else {			Element.addClassName(newDrawer.contentElement, 'first');			newDrawer.closedOffset = 0 - newDrawer.getHeight() + newDrawer.getHandleHeight() - 10;			newDrawer.indicateVisible();		}				//add drawer to the collection		this.drawers.push(newDrawer);	},		getWidth: function() {		return Element.getWidth(this.container);	},		getHeight: function() {		return Element.getHeight(this.container);	},		moveDrawer: function(drawer, x, y) {		new Effect.Move(drawer, {			x: x,			y: y, 			mode: 'absolute', 			transition: Effect.Transitions.sinoidal,			duration: this.drawerDuration});	}	});AC.ShingleDrawer = Class.create();Object.extend(Object.extend(AC.ShingleDrawer.prototype, AC.Drawer.prototype), {		openedOffset: 0,	closedOffset: 0,		previousDrawer: null,	nextDrawer: null,		isVisible: false,		trigger: function() {		if(!this.isVisible) {			this.open(true);			this.indicateVisible();		}	},		toggle: function() {				if(!this.isOpen) {			this.open();			this.indicateVisible();		} else {			this.close();		}			},		open: function(force) {				if (this.isOpen && !force) {			return;		}				if(this.previousDrawer !== null) {			this.previousDrawer.close();			this.previousDrawer.indicateObscured();		}				if(this.nextDrawer !== null) {			this.nextDrawer.open();			this.nextDrawer.indicateObscured();		}				this.indicateVisible();		this.isOpen = true;				this.bureau.moveDrawer(this.contentElement, 0, this.openedOffset);	},		close: function(force) {				if (!this.isOpen) {			return;		}				if (this == this.bureau.getLastDrawer()) {			return;		}				if(this.previousDrawer !== null) {			this.previousDrawer.close();		}				this.bureau.moveDrawer(this.contentElement, 0, this.closedOffset);		this.indicateObscured();		this.isOpen = false;			},		setPreviousDrawer: function(drawer) {		this.previousDrawer = drawer;				this.indicateObscured();				this.openedOffset = this.previousDrawer.openedOffset + this.previousDrawer.getHandleHeight() - 10;		Element.setStyle(this.contentElement, {top: this.openedOffset + "px"});	},		setNextDrawer: function(drawer) {		this.nextDrawer = drawer;				Element.removeClassName(this.contentElement, 'last');				if(this.previousDrawer != null) {			this.previousDrawer.setNextDrawer(this);		}				//ensure the previous drawer remains on top, part of the single effect		zIndex = parseInt(Element.getStyle(this.contentElement, 'zIndex'));		Element.setStyle(this.contentElement, {'zIndex': zIndex + 1});	},		indicateObscured: function() {		Element.addClassName(this.contentElement, 'obscured');		this.isVisible = false;	},		indicateVisible: function() {		this.isVisible = true;		Element.removeClassName(this.contentElement, 'obscured');	},		getHandleWidth: function() {		return Element.getWidth(this.handle);	},		getHandleHeight: function() {		return Element.getHeight(this.handle);	},		getWidth: function() {		return Element.getWidth(this.contentElement);	},		getHeight: function() {		return Element.getHeight(this.contentElement);	}		});/** * Section Bureau * One section open and visible at a time */AC.SectionBureau = Class.create();Object.extend(AC.SectionBureau.prototype, AC.Bureau.prototype);Object.extend(AC.SectionBureau.prototype, {		currentDrawer: null,	locked: false,		addDrawer: function(newDrawer) {		this.drawers.push(newDrawer);		newDrawer.handle.addClassName('obscured');		Element.hide(newDrawer.contentElement);	},	openingDrawer: function(drawer) {		if(this.currentDrawer != null) {			this.currentDrawer.close();		}				this.currentDrawer = drawer;	}	});AC.SectionDrawer = Class.create();Object.extend(AC.SectionDrawer.prototype, AC.Drawer.prototype);Object.extend(AC.SectionDrawer.prototype, {		isOpen: false,		trigger: function() {		this.toggle();	},		toggle: function() {				if(!this.isOpen) {			this.open();		}			},		open: function() {				if(this.bureau.locked) {			return;		}				var afterTransition = function() {			Element.show(this.contentElement);		}.bind(this);		//given an afterOpen callback, we need to stall in the very likely 		//scenario that we can't use the bureau again until the callback		//is completely finished. Onus is on the delegate to report finished				//but we also don't lock up the bureau unless we need to				if(typeof(this.afterOpen) == 'function') {			this.bureau.locked = true;			afterTransition = this.afterOpen.bind(this);		}				this.bureau.openingDrawer(this);				if(typeof(this.beforeOpen) == 'function') {			this.beforeOpen();		}				this.isOpen = true;		Element.removeClassName(this.handle, 'obscured');				new Effect.Appear(this.contentElement, {			afterFinish: afterTransition,			duration: this.transitionDuration,			queue: {scope: 'sectionalscope'}});			},		close: function() {				if(typeof(this.beforeClose) == 'function') {			this.beforeClose();		}				this.isOpen = false;		Element.addClassName(this.handle, 'obscured');						var afterTransition = function() {			if(typeof(this.afterClose) == 'function') {				this.afterClose();			}					}.bind(this)				new Effect.Fade(this.contentElement, {			afterFinish: afterTransition,			duration: this.transitionDuration,			queue: {scope: 'sectionalscope'}});			},		reportFinishedOpening: function() {		this.bureau.locked = false;	}	});