Esempio n. 1
0
File: url.ts Progetto: Teal/TealUI
    /**
     * 转换当前地址为字符串。
     */
    toString() {
        let auth = this.auth || "";
        if (auth) {
            auth = encodeURIComponent(auth).replace(/%3A/g, ":");
            auth += "@";
        }

        let protocol = this.protocol || "";
        let pathname = this.pathname || "";
        let hash = this.hash || "";
        let host: string | undefined;
        let query = "";

        if (this.host) {
            host = auth + this.host;
        } else if (this.hostname) {
            host = auth + (this.hostname.indexOf(":") === -1 ?
                this.hostname :
                "[" + this.hostname + "]");
            if (this.port) {
                host += ":" + this.port;
            }
        }

        if (this.query !== null && typeof this.query === "object")
            query = formatQuery(this.query);

        let search = this.search || (query && ("?" + query)) || "";

        if (protocol && protocol.charCodeAt(protocol.length - 1) !== 58/*:*/)
            protocol += ":";

        let newPathname = "";
        let lastPos = 0;
        for (let i = 0; i < pathname.length; ++i) {
            switch (pathname.charCodeAt(i)) {
                case 35: // '#'
                    if (i - lastPos > 0)
                        newPathname += pathname.slice(lastPos, i);
                    newPathname += "%23";
                    lastPos = i + 1;
                    break;
                case 63: // '?'
                    if (i - lastPos > 0)
                        newPathname += pathname.slice(lastPos, i);
                    newPathname += "%3F";
                    lastPos = i + 1;
                    break;
            }
        }
        if (lastPos > 0) {
            if (lastPos !== pathname.length)
                pathname = newPathname + pathname.slice(lastPos);
            else
                pathname = newPathname;
        }

        // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
        // unless they had them to begin with.
        if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== undefined) {
            host = "//" + (host || "");
            if (pathname && pathname.charCodeAt(0) !== 47/*/*/)
                pathname = "/" + pathname;
        } else if (!host) {
            host = "";
        }

        search = search.replace("#", "%23");

        if (hash && hash.charCodeAt(0) !== 35/*#*/) hash = "#" + hash;
        if (search && search.charCodeAt(0) !== 63/*?*/) search = "?" + search;

        return protocol + host + pathname + search + hash;
    }
Esempio n. 2
0
File: ajax.ts Progetto: Teal/TealUI
    /**
     * 发送当前的请求。
     * @return 如果请求发送成功则返回 true,否则返回 false。
     */
    send() {
        // 设置属性默认值。
        this.type = this.type || "GET";
        this.url = this.url || location.href;
        if (this.data != null && !(this.data instanceof FormData)) {
            this.contentType = this.contentType || "application/x-www-form-urlencoded";
            if (typeof this.data === "object") {
                this.data = this.contentType === "application/json" && this.type !== "GET" ? JSON.stringify(this.data) : formatQuery(this.data);
            }
            if (this.type === "GET") {
                this.url += (this.url.indexOf("?") >= 0 ? "&" : "?") + this.data;
                this.data = null;
            }
        }
        this.async = this.async !== false;

        // 准备请求。
        const xhr = this.xhr = new XMLHttpRequest();
        const end: Ajax["_end"] = this._end = (message, inerternalError) => {
            try {
                // 不重复执行回调。
                // 忽略 onreadystatechange 最后一次之前的调用。
                if (!this._end || (!inerternalError && xhr.readyState !== 4)) {
                    return;
                }
                delete this._end;

                // 删除 readystatechange  。
                xhr.onreadystatechange = null!;

                // 判断是否存在错误。
                if (inerternalError) {
                    this.status = inerternalError;
                    // 手动中止请求。
                    if (xhr.readyState !== 4) {
                        xhr.abort();
                    }
                } else {
                    this.status = xhr.status;
                    try {
                        this.statusText = xhr.statusText;
                    } catch (firefoxCrossDomainError) {
                        // 如果跨域,火狐会报错。
                        this.statusText = "";
                    }
                    if (checkStatus(this.status)) {
                        try {
                            this.responseText = xhr.responseText;
                        } catch (ieResponseTextError) {
                            // IE6-9:请求二进制格式的文件报错。
                            this.responseText = "";
                        }
                        message = null;
                    } else {
                        message = this.status + ": " + this.statusText;
                    }
                }
            } catch (firefoxAccessError) {
                return end(firefoxAccessError, -5);
            }

            // 执行用户回调。
            if (message) {
                this.error && this.error(message, this);
            } else {
                this.success && this.success(this.responseText, this);
            }
            this.complete && this.complete(message, this);
        };

        // 发送请求。
        try {
            if (this.username) {
                xhr.open(this.type, this.url, this.async, this.username, this.password);
            } else {
                xhr.open(this.type, this.url, this.async);
            }
        } catch (ieOpenError) {
            // IE: 地址错误时可能产生异常。
            end(ieOpenError, -3);
            return false;
        }
        for (const header in this.headers) {
            try {
                xhr.setRequestHeader(header, this.headers[header]);
            } catch (firefoxSetHeaderError) {
                // FF: 跨域时设置头可能产生异常。
            }
        }
        if (this.contentType) {
            try {
                xhr.setRequestHeader("Content-Type", this.contentType);
            } catch (firefoxSetHeaderError) {
                // FF: 跨域时设置头可能产生异常。
            }
        }
        if (this.withCredentials) {
            xhr.withCredentials = true;
        }
        try {
            xhr.send(this.data);
        } catch (sendError) {
            // 地址错误时产生异常 。
            end(sendError, -4);
            return false;
        }

        // 同步时火狐不会自动调用 onreadystatechange
        if (!this.async) {
            end(null, 0);
            return true;
        }

        // 绑定 onreadystatechange, 让 xhr 根据请求情况调用 done。
        xhr.onreadystatechange = end as any;

        if (this.timeout >= 0) {
            setTimeout(() => {
                end("Timeout", -2);
            }, this.timeout);
        }

        return true;
    }