function smtAjax() {this._construct()}(
    function() {
        var COUNT       = 0;
        var PENDING     = {};

        smtAjax.dataReady = function(id, text, js) {
            var th = PENDING[id];

            delete PENDING[id];

            if(th) {
                th._dataReady(text, js);
            }
        }

        smtAjax.prototype = {
            onreadystatechange: null,
            readyState:         0,
            responseText:       null,
            responseJS:         null,

            _span:              null,
            _id:                null,

            dummy: function() {},

            abort: function() {
                if(this._span) {
                    this.readyState = 0;

                    if(this.onreadystatechange) {
                        this.onreadystatechange();
                    }

                    this._cleanupScript();
                }
            },

            open: function(url) {
                this._openUrl = url;
                this._id      = null;

                return true;
            },

            send: function(content) {
                var href;
                var id = (new Date().getTime()) + "" + COUNT++;

                var query = this._hash2query(content);
                var url   = this._openUrl.replace(new RegExp('&amp;','g'), '&');
                var hash  = this.hash = url + '?' + query;

                href = url  + (url.indexOf('?')  >= 0 ? '&' : '?') + query;
                href = href + (href.indexOf('?') >= 0 ? '&' : '?') + "ajaxID=" + id;

                PENDING[id] = this;

                this._obtainScript(id, href);

                return true;
            },

            _construct: function() {},

            _dataReady: function(text, js) {
                with(this) {
                    if(text !== null || js !== null) {
                        readyState   = 4;
                        responseText = text;
                        responseJS   = js;
                    } else {
                        readyState   = 0;
                        responseText = responseJS = null;
                    }

                    if(onreadystatechange) {
                        onreadystatechange();
                    }

                    _cleanupScript();
                }
            },

            _obtainScript: function(id, href) {
                with(document) {
                    var span = null;

                    span = body.appendChild(createElement("SPAN"));
                    span.style.display = 'none';
                    span.innerHTML = 'IE.<s'+'cript></' + 'script>';

                    setTimeout(function() {
                        var s = span.getElementsByTagName("script")[0];

                        s.language = "JavaScript";

                        if(s.setAttribute) {
                            s.setAttribute('src', href);
                        } else {
                            s.src = href;
                        }
                    }, 10);

                    this._id   = id;
                    this._span = span;
                }
            },

            _cleanupScript: function() {
                var span = this._span;

                if(span) {
                    this._span = null;

                    setTimeout(function() {
                        span.parentNode.removeChild(span);
                    }, 50);
                }

                return false;
            },

            _hash2query: function(content, prefix) {
                if(prefix == null) {
                    prefix = "";
                }

                var query = [];

                if(content instanceof Object) {
                    for(var k in content) {
                        var v = content[k];

                        if (v == null || ((v.constructor||{}).prototype||{})[k]) {
                            continue;
                        }



                        var curPrefix = prefix ? prefix + '[' + this._escape(k) + ']' : this._escape(k);

                        if(v instanceof Object) {
                            query[query.length] = this._hash2query(v, curPrefix);
                        } else {
                            query[query.length] = curPrefix + "=" + this._escape(v);
                        }
                    }
                } else {
                    query = [content];
                }

                return query.join('&');
            },

            _escape: function(theText) {
                if(typeof encodeURIComponent == 'function') {
                    return encodeURIComponent(theText);
                } else {
                    return escape(theText).replace(new RegExp('\\+','g'), '%2B');
                }
            }
        }
    }
)();