2012-08-06 121 views
1

我已經編寫了一個非常基本的頁面與搜索文本輸入與Ajax自動完成。我將input onchange屬性設置爲調用一個ajax函數,該函數將從服務器檢索一組值,並將選項添加到關聯的數據列表中。 當我改變文本輸入中的某些內容時,JavaScript不會執行。但是,當我最小化窗口或單擊一個新的選項卡時,我確實執行了它,因此它不是語法問題,也不是我認爲的文件包含。 我也嘗試清除我的緩存,它沒有效果(並且我每次關閉它時,我的Firefox都完全清除)。這可能是由於什麼原因造成的? 我將粘貼我的源代碼: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.

任何想法? 感謝您的閱讀! :)

+1

2/3評論和文檔 - 1/3代碼 - 我的PM會佩服你:D – 2012-08-06 19:44:25

+0

雖然從頭開始寫點東西是一個很好的學習經歷,你可以用jquery在1行中做所有這些:) – jbabey 2012-08-06 20:02:07

回答

2

change事件不會被解僱,直到輸入失去焦點。您可能想要傾聽keyup或​​。

+0

感謝您的快速回答。但是如果我有多個自動完成的輸入呢?有沒有辦法使這個輸入「本地」? – Virus721 2012-08-06 19:43:24

+0

由於'ajaxAutoComplete'函數是通過元素ID進行參數化的,所以它應該可以正常工作。不過,可以考慮在你想要監控的所有輸入中添加一個「auto-complete」類,並通過Javascript註冊onchange回調,而不是HTML標記。編輯:我同意你應該使用一些庫來代替。 – Grampa 2012-08-06 19:50:46

+0

謝謝我會這麼做。此外,我已將事件從'onchange'更改爲'oninput',它工作正常。 – Virus721 2012-08-06 19:57:02

1

The change event僅當輸入失去焦點時纔會觸發。

更改事件發生在控件失去輸入焦點並且自獲得焦點後修改其值時。此事件對INPUT,SELECT和TEXTAREA有效。元件。

綁定到不同的事件。

還可以考慮使用現有的代碼/ widgets/libraries/etc。 - 我真的不知道這些車輪改造是否會讓你擺脫失去的時間。

+0

感謝您的回答。與Grampa相同的問題:D – Virus721 2012-08-06 19:44:16

+0

我編碼這是因爲我不想導入整個庫,當我只需要一個或兩個功能,也因爲我需要知道它是如何工作的。 – Virus721 2012-08-06 19:47:52

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); 
} 

的幾個注意事項,這不會與IE8或工作下由於缺乏支持,爲第三個參數setTimeout

+0

謝謝,我沒有想到這一點。這並不能解決我的問題,但接下來它肯定會有用。 – Virus721 2012-08-06 19:51:15

+0

oops。意在將其改爲onkeydown – SReject 2012-08-06 19:52:23