/*
 * Extensions to Element
 */
Element.addMethods({
	/**
	 * Starts a DelayedObserver for this element
	 */
	checkDelayed: function(element, func, delay, type, breakType) {
		return new DelayObserver(element, func, delay, type, breakType);
	}
});

/**
 * A DelayObserver calls a method after a certain delay.
 * This is mainly for input fields that should call a function after a few seconds of inactivity
 */
var DelayObserver = Class.create();
Object.extend(DelayObserver.prototype, {
	initialize: function(element, func, delay, type, breakType) {
		/**
		 * initialize the environment
		 */
		this._element = element;
		this._function = func;
		this._delay = (delay < 25) ? delay * 1000 : delay;
		
		this._timer = null;
		
		this._soon = this._soon.bindAsEventListener(this);
		this._break = this._break.bindAsEventListener(this);
		this._do = this._do.bindAsEventListener(this);
		
		/**
		 * breakType observings
		 */
		if (!Object.isUndefined(breakType)) {
			for (var i = 0; i < breakType.length; i++) {
				element.observe(type[i], this._break);
			}
		}
		
		/**
		 * type observings
		 */
		if (Object.isUndefined(type)) {
			element.observe('keyup', this._soon);
		} else if (Object.isArray(type)) {
			for (var i = 0; i < type.length; i++) {
				element.observe(type[i], this._soon);
			}
		}
	},
	
	/**
	 * starts the timer
	 */
	_soon: function() {
		this._clearTimer();
		this._timer = window.setTimeout(this._do,	this._delay);
	},
	
	/**
	 * this breaks a waiting timer
	 */
	_break: function() {
		if (this._timer != null) {
			this._clearTimer();
		}
	},

	/**
	 * clears the timer ... what else?
	 */	
	_clearTimer: function() {
		window.clearTimeout(this._timer);
		this._timer = null;
	},
	
	/**
	 * does what has to be done
	 */
	_do: function() {
		// call the function
		this._function();
		// clear the timer
		this._clearTimer();
	}
});

/**
 * EventListener
 * 
 * A Class that is mentioned to listen to certain calls
 */
var EventListener = Class.create();
Object.extend(EventListener.prototype, {
	initialize: function(type, func) {
		this.type = type;
		this.func = func || Prototype.emptyFunction;
	},
	
	getType: function() {
		return this.type;
	},
	
	getFunction: function() {
		return this.func;
	}
});

/**
 * Observable
 */
var Observable = Class.create();
Object.extend(Observable.prototype, {
	initialize: function() {
		this.listeners = [];
	},
	
	/**
	 * 
	 */
	fire: function() {
		var args = $A(arguments);
		var type = args.shift();
		for (var i = 0; i < this.listeners.length; i++) {
			var l = this.listeners[i];
			if (l.getType() == type) {
				l.getFunction().apply(this, args);
			}
		}
	},
	
  observe: function(type, func) {
  	for (var i = 0; i < this.listeners.length; i++) {
  		var l = this.listeners[i];
  		if (l.getType() == type && l.getFunction() == func) {
  			return;
  		}
  	}
  	this.listeners[i] = new EventListener(type, func);
  },
  
  stopObserving: function(type, func) {
  	for (var i = this.listeners.length - 1; i >= 0; i--) {
  		var l = this.listener[i];
  		if (l.getType() == type && l.getFunction() == func) {
  			this.listeners.splice(i, 1);
  		}
  	}
  },
  
  hasEventListeners: function(type) {
  	if (!Object.isUndefined(type)) {
  		for (var i = 0; i < this.listeners.length; i++) {
  			var l = this.listeners[i];
  			if (l.getType() == type) {
  				return true;
  			}
  		}
  		return false;
  	}
  	return this.listeners.length > 0;
  }
});

// follow first link
function ffl(id, event) {
  if (hna(event)) {
    location.href = $(id).select('A')[0].href;
  }
}

// has no anchor
function hna(event) {
  var e = event || window.event;
  if (e == null) {
    return false;
  }
  return Event.extend(e).findElement("a,button,input[@type='button']") == null;
}
