// simple synchronous ajax request
Object.extend(Ajax, {
    loadJSON: function(url, parameters) {
	var ret;
	new Ajax.Request(
	    url,
	    {
		parameters: parameters,
		asynchronous: false,
		onSuccess: function(transport, json) {
		    if (json == null) json = transport.responseText.evalJSON();
		    ret = json;
		}
	    }
	);
	return ret;
    }
});


// extend ajax request to handle timeouts.
Ajax.Request.prototype.initialize = Ajax.Request.prototype.initialize.wrap(function($proceed, url, options) {
    var _request_object = this; // stored here because the onCreate and onComplete callbacks are often bound to some other context. 

    options.onCreate = (options.onCreate || Prototype.emptyFunction).wrap(function($proceed) {
	_request_object.timeout_handle = function() {
	    var response = new Ajax.Response(_request_object);
	    var transport = _request_object.transport;
	    var readyState = transport.readyState;
	    _request_object.success = function() { return false; }
	    //0: Uninitialized - open() has not been called yet.
	    //1: Loading - send() has not been called yet.
	    //2: Loaded - send() has been called, headers and status are available.
	    //3: Interactive - Downloading, responseText holds the partial data.
	    //4: Completed - Finished with all operations.
	    switch(readyState) {
	    case 0:
	    case 1:
	    case 2:
	    case 3:
		transport.abort();
		if(options.onTimeout) options.onTimeout(response);
		break;
	    default:
		break;
	    }
	}.delay(options.timeout || 30); // default timeout: 30s
	return $proceed.apply(this, $A(arguments).slice(1));
    });
    
    options.onComplete = (options.onComplete || Prototype.emptyFunction).wrap(function($proceed) {
	window.clearTimeout(_request_object.timeout_handle);
	return $proceed.apply(this, $A(arguments).slice(1));
    });
    
    return $proceed.apply(Ajax.Request, $A(arguments).slice(1));
});



Element.addMethods({
    setVisibility: function(element, flag) {
	return element[flag ? 'show' : 'hide']();
    },
    
    isInViewport: function(element){
        return ( element.viewportOffset().top > 0 && 
                 element.viewportOffset().left > 0 &&
                 element.viewportOffset().top < document.viewport.getHeight() &&
                 element.viewportOffset().left < document.viewport.getWidth() );
	
    },
    scrollToUnlessVisible: function(element) {
	if(!element.isInViewport()) element.scrollTo();
    }
});

Date.prototype.getISODate = function() {
    return this.getFullYear() + '-' + (this.getMonth()+1) + '-' + this.getDate()
};
    
Date.fromString = function(str) {
    var sep = ['.', '/', '-'].find(function(sep) { return str.indexOf(sep) != -1; });
    var parts = str.split(sep);
    if(sep == '/' || sep == '-') parts = parts.reverse();
    
    var day = parts[0];
    var month = parts[1];
    var year = parts[2];
    return new Date(year, month-1, day);
};
    
var $EVAL = function(code) { // eval script in global scope.
    eval_function = (window.execScript ? window.execScript : (window.eval ? window.eval : eval));
    eval_function(code);
};

_js_loaded = [];
var $JS = function(url) { // include a javascript file (once);
    if(_js_loaded.indexOf(url) != -1) return;
    if($$("script[src=#{url}]".interpolate({url: url})).length != 0) return;
    new Ajax.Request(
	url, {
	    asynchronous: false,
	    evalJS: false,
	    onSuccess: function(transport) {
		_js_loaded.push(url);
	    $EVAL(transport.responseText);
	    }
	}
    );
};

_css_loaded = []
var $CSS = function(url) { // include a style sheet (once)
    if(_css_loaded.indexOf(url) != -1) return;
    if($$("link[href=#{url}]".interpolate({url: url})).length != 0) return;
    _css_loaded.push(url);
    document.observe("dom:loaded", function() {
	var link = new Element("link", { rel: "stylesheet", type: "text/css", href: url});
	$$('head').first().insert({ bottom: link});
    });
};

var $D = function(obj) { // debug
    if(console.debug) console.debug(obj);
};
    
$onLoad = function(f) {
    document.observe("dom:loaded", function() { f(); });
};
