Ajax.JsonRPC = Class.create(Ajax.Request, {
    initialize: function($super, func, args, callback, url, options) {
        options = options ? options : {};
        options.onComplete = this.jr_onComplete.bind({
            p_callback: callback,
            p_onComplete: options.onComplete
        });
        
        options.parameters = options.parameters ? options.parameters : {};
        options.parameters.jsonrpc = $H({'func': func, 'args': args}).toJSON();
        
        $super(url, options);
    },
    jr_onComplete: function(transport, param) {
        var response = transport.responseText.evalJSON();
        if (response) {
            if (response.exception) {
                alert('serverside exception: ' + response.exception);
            } else {
                this.p_callback(response.retval);
                this.p_onComplete(transport, param);
            }
        } else {
            alert('unable to decode Json-Reponse: ' + transport.responseText);
        }
    }
});

Element.addMethods('SELECT', {
    'createOption' : function(element, value, text) {
        element = $(element);
        
        var optionNode = document.createElement('option');
        var valueNode  = document.createAttribute('value');
        var textNode   = document.createTextNode(text);
        
        valueNode.nodeValue = value;
        
        optionNode.setAttributeNode(valueNode); 
        optionNode.appendChild(textNode);
        
        return optionNode;
    },
    
    'clearOptions' : function(element) {
        element = $(element);
        while(element.options.length > 0){
            element.options[0] = null;
        }
        return element;
    },
    
    'addOption' : function(element, value, text) {
        element = $(element);
        element.options[element.options.length] = new Option(text, value);
        return element;
    },
    
    'addOptions' : function(element, options) {
        element = $(element);
        for(var key in options){
            element.addOption(key, options[key]);
        }
        return element;
    },
    
    'removeOption' : function(element, value) {
        element = $(element);
        for(var i = 0; i < element.options.length; i++){
            if(element.options[i].value == value){
                element.options[i] = null;
                return element;
            }
        }
        return element;
    },
    
    'selectValue' : function(element, value) {
        element = $(element);
        for(var i = 0; i < element.options.length; i++){
            if(element.options[i].value == value){
                element.options[i].selected = true;
                return element;
            }
        }
        if(element.options.length > 0)
            element.options[0].selected = true;
        return element;
    },
    
    'selectText' : function(element, text) {
        element = $(element);
        for(var i = 0; i < element.options.length; i++){
            if(element.options[i].text == text){
                element.options[i].selected = true;
                return element;
            }
        }
        return element;
    },
    
    'updateOptions' : function(element, options) {
    	element = $(element);
    	var oldValue = $F(element);
    	element.clearOptions();
    	for (value in options) {
    		element.addOption(value, options[value]);
    	}
    	element.selectValue(oldValue);
    	return oldValue == $F(element);
    }
});

Element.addMethods({
    'display' : function(element, value) {
        element = $(element);
        element.setStyle({ 'display' : (value ? '' : 'none') } );
        return element;
    },
    
    'visibility' : function(element, value) {
        element = $(element);
        element.setStyle({ 'visibility' : (value ? 'visible' : 'hidden') } );
        return element;
    }
});

