// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults


/*  CORE OBJECT EXTENSIONS  */

String.prototype.trim_left = function() { return this.replace(/^\s+/,'') }
String.prototype.trim_right = function() { return this.replace(/\s+$/,'') }
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,'') }
String.prototype.insert = function(idx,value) { return this.slice(0,idx) + value + this.slice(idx) }
String.prototype.underscore = function() { return this.trim().replace(/ /g, '_').toLowerCase() }
String.prototype.replace_smart_characters = function(elements) {
	replacements = {
		"\xa0": " ",
		"\xa9": "(c)",
		"\xae": "(r)",
		"\xb7": "*",
		"\u2018": "'",
		"\u2019": "'",
		"\u201c": '"',
		"\u201d": '"',
		"\u2026": "...",
		"\u2002": " ",
		"\u2003": " ",
		"\u2009": " ",
		"\u2013": "-",
		"\u2014": "--",
		"\u2122": "(tm)"};
	regex = {};
	for (key in replacements) {
    regex[key] = new RegExp(key, 'g');
	}
	s = this;
	for (key in replacements) {
		s = s.replace(regex[key], replacements[key]);
	}
	return s;
};

Number.prototype.to_currency = function() {
	num = this.toString().replace(/\$|\,/g,'');
	if (isNaN(num)) 
		num = "0";
	var sign = (num == (num = Math.abs(num)));
	num = Math.floor(num * 100 + 0.50000000001);
	var cents = num % 100;
	num = Math.floor(num / 100).toString();
	if (cents < 10) 
		cents = "0" + cents;
	if (cents == 0)
		cents = '';
	else 
		cents = '.' + cents;
	for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
		num = num.substring(0, num.length - (4 * i + 3))+ ',' + num.substring(num.length - (4 * i + 3));
	return (((sign) ? '' : '-') + '$' + num + cents);
}

/*  / CORE OBJECT EXTENSIONS  */





/*  PROTOTYPE EXTENSIONS  */

Element.addMethods({
	
	getPadding: function(element) {
		element = $(element);
		var padding = {
			left: parseInt(element.getStyle('padding-left')),
			right: parseInt(element.getStyle('padding-right')),
			top: parseInt(element.getStyle('padding-top')),
			bottom: parseInt(element.getStyle('padding-bottom'))
		}
		return padding;
	},
	
	toggleBlind: function(element) {
		element = $(element);
		Element.visible(element) ? new Effect.BlindUp(element, {duration: 0.3}): new Effect.BlindDown(element, {duration: 0.2});
		return element;
	}
	
});

var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.currentlyExecuting = false;
		
    this._setFrequency(frequency);
  },

  execute: function() {
    this.callback(this);
  },

  _setFrequency: function(frequency){
    if(this.timer || frequency != this.frequency){
      clearInterval(this.timer);
      this.timer = null;
    }

    if(frequency > 0){
      this.timer = setInterval(this.onTimerEvent.bind(this), frequency * 1000);
      this.frequency = frequency;
    }
  },

  stop: function() {
    this._setFrequency(0);
  },

  start: function(frequency){
    if(Object.isUndefined(frequency)) frequency = this.frequency;
    this._setFrequency(frequency);
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.execute();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
});


/*  / PROTOTYPE EXTENSIONS  */






/*  flash utilities  */

screen_dims = function() {
	dims = new Array();
	dims[0] = document.viewport.getWidth();
	dims[1] = document.viewport.getHeight();
	return dims;
}

resize_flash = function(element, new_width, new_height) {
	element = $(element);
	element.setStyle({width: new_width + 'px', height: new_height + 'px'})
}

hide_flash = function(element, delay) {
	flash_element_to_hide = $(element)
	hide_flash_timer = setTimeout("Effect.BlindUp(flash_element_to_hide, {duration: 0.5})", delay);	
}

/*  / flash utilities  */





/*  form helpers  */

clear_alerts = function(form) {
	Element.extend(form).descendants().each( function(e){ e.removeClassName('alert') });
}

/* duplicate_has_many_form_elements */
/*
	duplicates a generic set of form elements, increments them, and adds them to a div in a form
	so that has_many properties can be dynamically added without refreshing the form
	one bit of kludgy magic is to replace all instances of 'xx' with id_offset + a counter
	and 'xx1' with id_offset + a counter + 1 (for 1 indexed titles)
*/
duplicate_has_many_form_elements = function(target_div, div_to_copy, id_offset) {
	var target_div = $(target_div);
	var div_to_copy = $(div_to_copy);
	var count = target_div.immediateDescendants().length + id_offset;
	var copied_div = div_to_copy.clone(true);
	copied_div.id = copied_div.id + count;
	copied_div.innerHTML = copied_div.innerHTML.gsub(/xx1/, count + 1);
	copied_div.innerHTML = copied_div.innerHTML.gsub(/xx/, count);
	target_div.appendChild(copied_div);
	copied_div.show();
}

/*  / form helpers  */




/*  image gallery  */
/*  
		slideshow widget
		json_array_of_images is a number of objects of the form:
    	{file: image_filename, description: description to go under image, link: page to link text to (optional)}
		options are:
			delay: slideshow delay, in seconds (default 5)
			overlay: image to use as a mask above other images
*/
var ImageGallery = Class.create({
	initialize: function(parent_div, json_array_of_images, options) {

		if (options == undefined) options = {}; 
		this.parent_div = $(parent_div);
		this.image = Element.extend(document.createElement('DIV'));
		this.image.addClassName('image');
		this.parent_div.appendChild(this.image);
		
		this.text = Element.extend(document.createElement('DIV'));
		this.text.addClassName('text');
		this.parent_div.appendChild(this.text);
		
		if (options.overlay != undefined) {
			this.image_overlay = Element.extend(document.createElement('DIV'));
			this.image_overlay.addClassName('image_overlay');
			var anchor = Element.extend(document.createElement('A'));
			anchor.onmouseover = this.pause_slideshow.bind(this);
			anchor.onmouseout = this.resume_slideshow.bind(this);
			var img = Element.extend(document.createElement('IMG'));
			img.src = options.overlay;
			anchor.appendChild(img);
			this.image_overlay.appendChild(anchor);
			this.parent_div.appendChild(this.image_overlay);
			this.image_overlay.setStyle({display: 'none'})
		}
		
		this.current_image = 0;
		this.image_data = json_array_of_images;
		this.delay = (options.delay != undefined) ? options.delay : 5;
		
		this.create_image_list();
		this.create_description_list();
		Event.observe(window, 'load', this.start_slideshow.bindAsEventListener(this));
  },

	start_slideshow: function(event) {
		this.image_list.setStyle({display: 'block'});
		this.description_list.setStyle({display: 'block'});
		this.show_image();
		this.timer = new PeriodicalExecuter(this.show_image.bind(this), this.delay)
	},

	pause_slideshow: function() {
		this.timer.stop();
	},

	resume_slideshow: function() {
		this.show_image();
		this.timer.start();
	},

	create_image_list:function() {
		this.image_list = Element.extend(document.createElement('UL'));
		this.image_list.setStyle({display: 'none'});
		var image_list_width = 0;
		for (var i=0; i < this.image_data.length; i++) {
			var obj = this.image_data[i];
			var li = Element.extend(document.createElement('LI'));
			var anchor = Element.extend(document.createElement('A'));
			anchor.href = obj.link;
			anchor.onmouseover = this.pause_slideshow.bind(this);
			anchor.onmouseout = this.resume_slideshow.bind(this);
			var img = Element.extend(document.createElement('IMG'));
			img.alt = obj.description;
			img.src = obj.file;
			anchor.appendChild(img);
			li.appendChild(anchor);
			this.image_list.appendChild(li);
		}
		this.image.appendChild(this.image_list);
	},
	
	create_description_list:function() {
		this.description_list = Element.extend(document.createElement('UL'));
		this.description_list.setStyle({display: 'none'});
		for (var i=0; i < this.image_data.length; i++) {
			var obj = this.image_data[i];
			var li = Element.extend(document.createElement('LI'));
			var span = Element.extend(document.createElement('SPAN'));
			span.innerHTML = obj.description + " &nbsp; ";
			li.appendChild(span);
			if ((obj.link != undefined) && (obj.link != "")){
				var a = Element.extend(document.createElement('A'));
				a.href = obj.link;
				a.title = "Learn more";
				a.innerHTML = "Learn more --&raquo;"
				li.appendChild(a);
			}
			this.description_list.appendChild(li);
		}
		this.text.appendChild(this.description_list);
	},

	show_image: function() {
		this.current_image += 1;
		if (!this.image_overlay.visible()) { // first time, need to initialize
			this.image_overlay.show();
			var wt = this.image_overlay.getWidth();
			var ht = this.image_overlay.getHeight();
			this.image.setStyle({width: wt + 'px', height: ht + 'px', overflow: 'hidden'});
			if (!this.image.visible()) this.image.show();
			if (!this.text.visible()) this.text.show();
			this.image_list.immediateDescendants().each(function(e) {
				var ul_width = e.up('ul').getWidth();
				var img_width = e.down('img').getWidth();
				e.up('ul').setStyle({width: ul_width + img_width + 'px'});
			});
		}
		if (this.current_image > this.image_list.immediateDescendants().length) 
			this.current_image = 1;
		var image_list_margin = 0;
		var description_list_margin = 0;
		for (var i=0; i < this.current_image - 1; i++) {
			image_list_margin -= this.image_list.immediateDescendants()[i].down('IMG').getWidth();
			description_list_margin -= 1.5;
		}
		if (this.image_overlay != undefined) {
			var link = this.image_list.immediateDescendants()[this.current_image - 1].down('A').href;
			this.image_overlay.down('A').href = link;
		}
		new Effect.Morph(this.image_list, {style: {marginLeft: image_list_margin + 'px'}, duration: 0.5});
		new Effect.Morph(this.description_list, {style: {marginTop: description_list_margin + 'em'}, duration: 0.5});
	}
})
  