    function LAjax(uri)
    {
        // check input
        if ( ! uri ){ alert("FATAL: uri should be set"); }

        // member variables
        this._uri            = uri   ;
        this._debug_mode     = false ;
        this._request_method = "GET" ;
        this._callback       = undefined;

        // member functions
        this.debug_mode     = LAjax_debug_mode     ;
        this.request_method = LAjax_request_method ;
        this.set_callback   = LAjax_set_callback   ;
        this.rpc            = LAjax_rpc            ;
        this.init_xmlhttp   = LAjax_init_xmlhttp   ;
        this.debug          = LAjax_debug          ;
    }

    function LAjax_rpc( function_name, args )
    {
        var query_string;
        { // put function name in query-string
            query_string = "rs=" + escape(function_name)

            // add parameters to query-string
            for ( i = 0; i < args.length; i++ ){
                if ( i == 0 ) query_string += "&rsargs=";
                if ( i >  0 ) query_string += "%26amp%3B"; // uri-encoded(&)
                query_string += escape(args[i]);
            }
        }

        // GET => modify the uri, POST => set post_data
        var post_data = "";
        var uri       = this._uri;
        {
            if (this.request_method() == "GET") {
                uri += ((uri.indexOf('?') == -1) ? '?' : '&') + query_string;
            }
            else if (this.request_method() == "POST") {
                post_data = query_string;
            }
        }

        this.debug("function_name = " + function_name + "\n"
                 + "uri           = " + uri           + "\n"
                 + "post_data     = " + post_data     + "\n");

        // Initialize connection
        var xmlhttp = this.init_xmlhttp();
        xmlhttp.open(this.request_method(), uri, true);

        // set POST headers
        if (this.request_method() == "POST") {
            xmlhttp.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
            xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        }

        var ajaxObject = this;

        // connect, if success put result in jsStructDump
        xmlhttp.onreadystatechange = function()
        {
            if (xmlhttp.readyState == 4) {
                var status = xmlhttp.responseText.charAt(0);
                var data   = xmlhttp.responseText.substring(2);
                if (status == "-") {
                    ajaxObject.debug("Error: " + data);
                }
                else if (status == "+") {
                    var jsStructDump = data;

                    ajaxObject.debug( 'jsStructDump = ' + jsStructDump );

                    // convert jsdumper to actual jsstruct
                    var jsstruct = JSON.parse(jsStructDump);

                    ajaxObject.debug( 'jsstruct = ' + jsstruct );

                    ajaxObject._callback(jsstruct);
                }
                else {
                    ajaxObject.debug("Unknown return code: " + xmlhttp.responseText);
                }
            }
        }
        xmlhttp.send(post_data);

        // close connection
        delete xmlhttp;
    }

    function LAjax_init_xmlhttp()
    {
        this.debug("init_xmlhttp() called..");

        var xmlhttp;

        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (oc) {
                xmlhttp = null;
            }
        }
        if( ! xmlhttp && typeof XMLHttpRequest != "undefined"){
            xmlhttp = new XMLHttpRequest();
        }
        if ( !xmlhttp ){
            this.debug("Could not create connection object.");
        }
    
        return xmlhttp;
    }

    function LAjax_set_callback(callback)
    {
//-T- suppose I could pass arguments through here 
        if ( arguments.length != 1 ){
            alert('FATAL: set_callback should have exactly one argument');
        }

        this._callback = callback;
    }

    function LAjax_debug_mode( debug_mode )
    {
        if ( arguments.length > 0 ){
            if ( this.debug_mode.arguments[0] ){ this._debug_mode = true ; }
            else                                { this._debug_mode = false; }
        }

        return this._debug_mode;
    }

    function LAjax_request_method( request_method )
    {
        if ( arguments.length > 0 ){

            if ( request_method == 'GET' || request_method == 'POST' ){
                this._request_method = request_method;
            }
            else {
                alert("FATAL: invalid request method: " + request_method);
            }
        }

        return this._request_method;
    }

    function LAjax_debug(text)
    {
        if ( this.debug_mode() ) {
            alert("DEBUG: " + text);
        }
    }
