// Spread the contents of a container horizontally. Contents are assumed to share
// the same element tag name. The optional filter parameter specifies a class to
// which an element must belong; this option is useful when handling pull-down menus
// implemented as nested lists. R. Abeles 11/16/2007.

// 06/09/2008 rabeles: use lMargin to balance spread() presentation
// 07/08/2008 rabeles: correct off-by-one error in FireFox 3.0

function spread(container, elements, filter)
{
	container = $(container);
	elements = $A(container.getElementsByTagName(elements));
	var cWidth = container.getWidth();
	cWidth -= (parseInt(container.getStyle('padding-left')));
	cWidth -= (parseInt(container.getStyle('padding-right')));
	var eWidth = 0;
	var eCtr = 0;
	
	elements.each(function (e) {
		e = $(e);
		if ((filter == null) || (e.hasClassName(filter))) {
			eCtr++;
			eWidth += e.getWidth();
			e.setStyle( {marginLeft: 0, marginRight: 0} );
		}
	});
	
	// FF 3.0 appears to have an off-by-one error, so we sacrifice a pixel	
	var cFill = cWidth - eWidth - 1;
	
	if ((cFill > 0) && (eCtr > 1)) {
		var eMargin = Math.floor(cFill / (eCtr - 1));
		var lMargin = 0;
		var rMargin = 0;
		cFill -= eMargin * (eCtr - 1);
		if (cFill > 0) {
			rMargin = Math.floor(cFill / 2);
			lMargin = cFill - rMargin;
		}
		var first = true;
		elements.each(function (e) {
			if ((filter == null) || (e.hasClassName(filter))) {
				eCtr--;
				if (first) {
					e.setStyle( {marginLeft: lMargin + 'px'} );
					first = false;
				}
				if (eCtr != 0) {
					e.setStyle( {marginRight: eMargin + 'px'} );
				} else {
					e.setStyle( {marginRight: rMargin + 'px'} );
				}
			}
		});
	}
}

function spread2(container, container2, etag, filter)
{
	container = $(container);
	container2 = $(container2);
	var elements = $A(container.getElementsByTagName(etag));
	var cWidth = container.getWidth();
	cWidth -= (parseInt(container.getStyle('padding-left')));
	var eWidth = 0;
	var eCtr = 0;
	
	elements.each(function (e) {
		e = $(e);
		if ((filter == null) || (e.hasClassName(filter))) {
			eCtr++;
			eWidth += e.getWidth();
			e.setStyle( {marginLeft: 0, marginRight: 0} );
		}
	});
	
	var cFill = cWidth - eWidth;
	
	if ((cFill > 0) && (eCtr > 1)) {
		var eMargin = Math.floor(cFill / (eCtr - 1));
		var lMargin = 0;
		var rMargin = 0;
		cFill -= eMargin * (eCtr - 1);
		if (cFill > 0) {
			rMargin = Math.floor(cFill / 2);
			lMargin = cFill - rMargin;
		}
		var first = true;
		elements.each(function (e) {
			if ((filter == null) || (e.hasClassName(filter))) {
				eCtr--;
				if (first) {
					first = false;
				}
				if (eCtr != 0) {
					e.setStyle( {marginRight: eMargin + 'px'} );
				} else {
					e.setStyle( {marginRight: rMargin + 'px'} );
				}
			}
		});

		elements = $A(container2.getElementsByTagName(etag));

		elements.each(function (e) {
			e = $(e);
			if ((filter == null) || (e.hasClassName(filter))) {
				e.setStyle( {marginLeft: 0, marginRight: eMargin + 'px'} );
			}
		});
	}
}

function balance(left, right, overhang) {
	left = $(left);
	right = $(right);
	
	var lBot = left.getHeight() + Position.cumulativeOffset(left)[1];
	var rBot = right.getHeight() + Position.cumulativeOffset(right)[1];
		
	if (rBot < (lBot + overhang)) {
		var rPad = right.getHeight();
		var rAdj = lBot + overhang - rBot;
		rPad += rAdj;
		right.setStyle({height: rPad + 'px'});
	}
}

function align(left, right) {
	left = $(left);
	right = $(right);
	
	var lTop = Position.cumulativeOffset(left)[1];
	var rTop = Position.cumulativeOffset(right)[1];
	
	if (rTop < lTop) {
		var rPad = parseInt(left.getStyle('padding-top'));
		rPad += (lTop - rTop);
		right.setStyle({paddingTop: rPad + 'px'});
	}
}

// Modified scriptaculous combined effect Pulsate. Now takes the following optional
//  parameters:
//	
//	startOpacity	element begins pulse at this opacity value
//	endOpacity		element ends half-cycle of pulse at this opacity value
//	oldOpacity		element opacity at end of pulse effect (usually same as startOpacity,
//					if omitted, behavior defaults to the original scriptaculous behavior
//					that exhibits odd artifacts if pulsate is started multiple times on
//					the same element.
//					already in progress on the selected element.
//	duration		floating-point total seconds in pulse effect
//	transition		transition effect (defaults to Effect.Transitions.sinoidal)
//	pulses			number of times pulse effect repeats
//	afterFinish		function(element) that fires after the effect finishes
//
Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || { };
  var startOpacity = options.startOpacity || 0.0;
  var endOpacity = options.endOpacity || 1.0;
  var oldOpacity = options.oldOpacity || element.getInlineOpacity();
  var duration = options.duration || 2.0;
  var transition = options.transition || Effect.Transitions.sinoidal;
  var pulses = options.pulses || 3;
  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos, pulses)) };
  reverser.bind(transition);
  var afterFinish = options.afterFinish || Prototype.emptyFunction;
  return new Effect.Opacity(element, 
	Object.extend(Object.extend({  duration: duration, from: endOpacity, to: startOpacity,
	  afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); afterFinish(effect.element);}
	}, options), {transition: reverser}));
};

// Event observer that begins pulsation. Serialized by this.__pulsate.
//
function pulsate(event) {
	if (Object.isUndefined(this.__pulsate) || !this.__pulsate) {
		this.__pulsate = true;
		Effect.Pulsate(this, {pulses: 2,
                              startOpacity: 0.45,
                              endOpacity: 1.0,
                              oldOpacity: 0.45,
                              duration: 3.0,
                              afterFinish: function(element) {element.__pulsate = false;}
		                     });	
	}	
}

//--------------------------------------
// Portfolio page UA implementation
//
//--------------------------------------
function port_initialize(container) {
	// install focus handlers on each thumbnail button object in the tray container; select the first button/slide for display

	var container_obj = $(container);
	container_obj.next_slide = '';
	container_obj.animating = false;

	var elements = container_obj.select('li.port_nav_button');
	var idx = 0;
	elements.each(function(e) {
		Event.observe(e, 'click', bfocus_in.bindAsEventListener(e, elements));
		Event.observe(e, 'mouseout',  bfocus_out.bindAsEventListener(e, elements));
		if (idx == 0) {
			e.port_focus = true;
			e.addClassName('port_nav_button_selected');
		} else {
			e.port_focus = false;
		}
		e.port_slide = 'port_pix_frame' + idx;
		e.port_frame = container;
		$(e.port_slide).port_button = e;
		idx++;
	});
}

function bfocus_in(event, elements) {
	// serialize animation and ignore re-selection of current slide
	var frame = $(this.port_frame);
	if (this.port_focus)
		return;
	if (frame.animating) {
		frame.next_slide = this;
		return;
	}
	frame.animating = true;
	// remove focus from previous button / start transition-out on current slide
	elements.each(function(e) {
		if (e.port_focus == true) {
			e.port_focus = false;
			Effect.Fade(e.port_slide, {duration: 0.5,
                                       queue: 'end',
                                       afterFinish: function(e) {e.element.port_button.removeClassName('port_nav_button_selected');}});
		}
	});
	// give focus to current button / start transition-in on current slide
	this.port_focus = true;
	Effect.Appear(this.port_slide, {duration: 0.5,
                                    queue: 'end',
                                    afterSetup: function(e) {
						e.element.port_button.addClassName('port_nav_button_selected');
                                    },
									afterFinish: function(e) {
                        var frame = $(e.element.port_button.port_frame);
                        frame.animating = false;
                        if (frame.next_slide != '') {
                          // fake mouseover event to switch to next_slide
                          var next_button = frame.next_slide;
                          frame.next_slide = '';
                          bfocus_in.bind(next_button)('', elements);
                        }
                                    }});
}

function bfocus_out(event, elements) {
}

// based on suckerfish hover workaround for internet explorer
function ie_hover_fix() {
	if (Prototype.Browser.IE) {
		// The devil lives in Redmond. 
		var ar_version = navigator.appVersion.split("MSIE");
		var ie_version = parseFloat(ar_version[1]);
		
		if ((ie_version >= 5.5) && (ie_version < 7.0)) {
			var elements = $$('.hover_hover');
			elements.each(function(e) {
				Event.observe(e, 'mouseover', hover_on.bindAsEventListener(e));
				Event.observe(e, 'mouseout',  hover_off.bindAsEventListener(e));
			});
		}
	} 
}

function hover_on() {
	this.addClassName('ie_hover');
}

function hover_off() {
	this.removeClassName('ie_hover');
}

function start_slideshow(slide_id, start_frame, end_frame, delay) {
	setTimeout(switch_slides(slide_id, start_frame, start_frame, end_frame, delay), delay);
}

function switch_slides(slide_id, frame, start_frame, end_frame, delay) {
	return (function() {
		Effect.Fade(slide_id + frame, {duration: 1.5, queue: 'end'});
		frame = (frame == end_frame)? start_frame : frame + 1;
		Effect.Appear(slide_id + frame, {duration: 1.5, queue: 'end'});
		setTimeout(switch_slides(slide_id, frame, start_frame, end_frame, delay), delay + 3000);
	})
}

