1

我编写了一个非常基本的页面,其中包含带有 ajax 自动完成功能的搜索文本输入。我已将输入 onchange 属性设置为调用一个 ajax 函数,该函数将从服务器检索一组值,并将选项添加到关联的数据列表。当我在文本输入中更改某些内容时,JavaScript 不会执行。但是,当我最小化窗口或单击新选项卡时,我会执行它,所以我想这既不是语法问题也不是文件包含问题。我还试图清除我的缓存,因为它没有任何效果(无论如何每次我关闭它时我的 Firefox 都被完全清除)。这可能是因为什么?我将粘贴我的源代码:

我的 AJAX 课程。它确实有效,我在工作中对其进行了测试,并且效果很好。不用看,我贴上来,方便大家看。

/**
* @file ajax.js
* @version 1.0 - 2012-07-30
* @author *****
* @brief This file describes a class allowing to easily perform AJAX requests.
*/

/**
* @class Ajax
* @brief Used to performs AJAX requests.
* @details Usage example :
*
* var request1 = new Ajax()
*     .url('some_url')
*     .parameters('some_parameters')
*     .callback(function(xhr) { alert(xhr.responseText); })
*     .method('GET')
*     .execute();
*
* var request2 = new Ajax();
* request2.url('some_url');
* request2.parameters('some_parameters');
* request2.callback(function(xhr) { alert(xhr.responseXml); });
* request2.execute();
*
* Using setters is not necessary, properties can be set manually. Setters only allow to chain calls by returning this.
* The order in which properties are set does not matter as long as the mandatory ones are set before calling 'execute'.
* If the server returns a string it can be retrieved from xhr.responseText. If it returns an XML file, it will be in
* xhr.responseXml.
*/
function Ajax()
{
    /**
    * @brief (string) URL of the request (MANDATORY).
    * @details It main contain parameters, but if so, the property 'parameters' should be used instead.
    */
    var url;

    /**
    * @brief (string) Method to use for the request.
    * @details Can be either 'GET' or 'POST'.
    */
    var method = 'POST';

    /**
    * @brief Function to be called once the request has been performed.
    * @details This callback function will be given the XMLHttpRequest object as a parameter.
    */
    var callback;

    /**
    * @brief Parameters of the URL.
    * @details Must be in the following format : 'arg1=value1&arg2=value2'... and contain no question mark.
    */
    var parameters;

    /**
    * @brief Indicates if the request is syncrhonous.
    */
    var wait = false;

    /**
    * @brief Sets the 'url' property.
    * @details Returns the object to chain setter calls.
    * @param String.
    * @return Ajax.
    */
    this.url = function($url) { url = $url; return this; };

    /**
    * @brief Sets the 'method' property.
    * @details Returns the object to chain setter calls.
    * @param String.
    * @return Ajax.
    */
    this.method = function($method) { method = $method; return this; };

    /**
    * @brief Sets the 'callback' property.
    * @details Returns the object to chain setter calls.
    * @param Function.
    * @return Ajax.
    */
    this.callback = function($callback) { callback = $callback; return this; };

    /**
    * @brief Sets the 'parameters' property.
    * @details Returns the object to chain setter calls. WARNING : Using parameters will change the method to POST. If
    * parameters must be passed using GET, they must be included in the URL.
    * @param String.
    * @return Ajax.
    */
    this.parameters = function($parameters) { parameters = $parameters; method = 'POST'; return this; };

    this.wait = function($wait) { wait = $wait; return this; };

    // FIXME POST semble poser probleme lorsque l'on renvoie du json et que l'on l'éval.

    /**
    * @brief Performs the AJAX request.
    * @details The mandatory properties must be set before calling this method.
    */
    this.execute = function()
    {
        var xhr = null;

        try { xhr = new XMLHttpRequest();  }
        catch(e) { 
            try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } 
            catch(e2) { 
                try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } 
                catch(e) {}
            }
        }

        var self = this;

        xhr.onreadystatechange = function() {
            if(4 === xhr.readyState && 200 === xhr.status) {
                if(callback) return callback(xhr);
            }
        };

        xhr.open(method, url, !wait);

        if('POST' === method) xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        xhr.send(parameters ? parameters : null);

        return this;
    };

    return this;
}

我的 AJAX 自动完成功能:

function ajaxAutoComplete(inputId)
{
    var input = document.getElementById(inputId);
    if(null === input) alert('ajaxAutoComplete : invalid input ID.');

    if(!input.list) alert('ajaxAutoComplete : input has no associated data list');

    var list = document.getElementById(input.list.id);
    if(null === list) alert('ajaxAutoComplete : input has an invalid list ID.');

    var suggestions;

    new Ajax()
        .url('../Controller/index.php?exec=ajaxAutoComplete')
        .parameters('searchInput=' + input.value)
        .callback(function(xhr)
        {
            suggestions = eval('(' + xhr.responseText + ')');

            while(list.hasChildNode) list.removeChild(list.firstChild);

            for(var i = 0; i < suggestions.length; ++i)
            {
                var option = document.createElement('option');
                option.value = suggestions[i];
                list.appendChild(option);
            }
        })
        .wait(false)
        .execute();

} // ajaxAutoComplete()

和 HTML 代码:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Module</title>
        <meta charset="utf-8">
        <script type="text/javascript" src="../Js/main_dev.js"></script>
    </head>
    <body>
        <header>
            <h1>Image module</h1>
        </header>
        <nav>
            <form action="#" method="#">
                <fieldset>
                    <label for="searchInput">Search</label>
                    <input id="searchInput" list="searchSuggestions" name="searchInput" type="text" value="search" maxlength="255" onchange="ajaxAutoComplete(this.id)">
                    <datalist id="searchSuggestions">
                    </datalist>
                    <input type="submit" value="Search">
                </fieldset>
            </form>
        </nav>
        <div class="Content">
        </div>
        <footer>
            <span></span>
        </footer>
    </body>
</html>

服务器返回一个由随机生成的数字组成的 JSON 编码数组,例如:[1611, 1515187, 415417, 7815, 587187]

我正在使用 Firefox 14。

有任何想法吗 ?谢谢阅读 !:)

4

3 回答 3

2

在输入失去焦点之前,该change事件不会被触发。您可能想听keyupkeydown代替。

于 2012-08-06T19:41:06.467 回答
1

change事件仅在输入失去焦点时触发。

当控件失去输入焦点并且其值在获得焦点后已被修改时,会发生更改事件。此事件对 INPUT、SELECT 和 TEXTAREA 有效。元素。

绑定到不同的事件。

还可以考虑使用现有的代码/小部件//等。– 除了浪费时间之外,我真的不明白所有这些重新发明的轮子应该为您带来什么。

于 2012-08-06T19:41:13.523 回答
0

我建议不要为每个按下的字符进行 AJAX 调用。将请求延迟片刻,以查看用户是否仍在键入。否则,您最终可能会解析前一个字母的 json,就好像它是当前的一样。为此,只需创建一个简单的队列:

<input id="searchInput" list="searchSuggestions" name="searchInput" type="text" value="search" maxlength="255" onkeydown="queueRequest(this.id)">

然后你的 Javascript 看起来像

function queueRequest(id) {
    if (queuedRequest) clearTimeout(queuedRequest);
    window.queuedRequest = setTimeout(function(id) {
        ajaxAutoComplete(id);
    },100,id);
}

一些注意事项,由于缺乏对 setTimeout 的第三个参数的支持,这不适用于 IE8 或更低版本

于 2012-08-06T19:48:50.130 回答