2011-11-22 96 views
1

我有以下循環。目標是當用戶在下拉列表中選擇某些選項時自動顯示文本框。意外的JS/jQuery循環行爲

出於某種原因,在以下代碼中,循環將「贊助者」字段分配給關聯數組以用於「blurb」。我無法弄清楚爲什麼。我該如何做這項工作?

非常感謝。

function add_fields_on_change() 
{ 
    var map = { 
     "sponsor" : Array("New Sponsor", "new_sponsor"), 
     "blurb"  : Array("New Blurb Suggestion", "new_blurb") 
    }; 
    for (field in map) 
    { 
     alert($('.bound[name='+field+']').val()); //alerts as expected 
     $('.bound[name='+field+']').change(function() { 
      alert(map[field][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields 
      if ($(this).val() == map[field][0]) 
      { 
       $('.hidden[name='+map[field][1]+']').show(); 
      } 
     }); 
    } 
} 
+0

你真的應該使用'[「New Sponsor」,「new_sponsor」]'創建一個數組。使用'Array'可能會導致令人驚訝的怪癖 - 請參閱Array(2)'返回的內容。 – pimvdb

回答

4

的原因是,你要創建(這是一個閉合)事件處理程序有一個持久參考field變量,而不是複製它作爲創建功能時的感覺。因此,所有創建的事件處理程序都會看到相同的值field(分配給它的最後一個值)。

因爲你已經在使用jQuery的,最簡單的解決辦法可能是使用$.each

function add_fields_on_change() 
{ 
    var map = { 
     "sponsor" : Array("New Sponsor", "new_sponsor"), 
     "blurb"  : Array("New Blurb Suggestion", "new_blurb") 
    }; 
    $.each(map, function(field, value) { 
     alert($('.bound[name='+field+']').val()); //alerts as expected 
     $('.bound[name='+field+']').change(function() { 
      alert(map[field][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields 
      if ($(this).val() == map[field][0]) 
      { 
       $('.hidden[name='+map[field][2]+']').show(); 
      } 
     }); 
    }); 
} 

這工作,因爲該事件處理程序密切在呼叫你傳遞each迭代器功能,所以他們每個人都得到自己的field參數,這從來沒有改變。

如果你想做到這一點,而無需使用$.each不管出於什麼原因,你會做這樣的事情:

function add_fields_on_change() 
{ 
    var map = { 
     "sponsor" : Array("New Sponsor", "new_sponsor"), 
     "blurb"  : Array("New Blurb Suggestion", "new_blurb") 
    }; 
    var field; 
    for (field in map) 
    { 
     alert($('.bound[name='+field+']').val()); //alerts as expected 
     $('.bound[name='+field+']').change(createHandler(field)); 
    } 

    function createHandler(f) { 
     return function() { 
      alert(map[f][0]); //alerts "New Blurb Suggestion" for both "sponsor" and "blurb" fields 
      if ($(this).val() == map[f][0]) 
      { 
       $('.hidden[name='+map[f][3]+']').show(); 
      } 
     }; 
    } 
} 

這是同樣的原理,事件處理程序關閉了調用createHandler並使用f參數,這對每次調用都是唯一的,而且我們永遠不會分配新的值。

請注意,我聲明瞭field變量。您的原始代碼缺少該聲明,這意味着您正在墮入Horror of Implicit Globals

更多閱讀:

+0

這是有道理的。在功能上,有沒有更好的方法來重寫?顯然,我可以對這些關聯中的每一個進行硬編碼,但是我試圖使其具有可擴展性,因爲我有一種感覺,那就是希望在此表單上使用其他選項來執行類似操作。 –

+0

Ahhh..Interesting。我沒有想過每個人都這樣使用。這解決了它!謝謝!將盡快接受。 –

+0

感謝您的其他方法和進一步閱讀。所有超級有用。 –

0

您可以通過添加自定義屬性到你的領域,避免了倒閉的問題做到這一點:

function add_fields_on_change() 
{ 
    var map = { 
     "sponsor" : Array("New Sponsor", "new_sponsor"), 
     "blurb"  : Array("New Blurb Suggestion", "new_blurb") 
    }; 
    for (field in map) 
    { 
     $('.bound[name='+field+']').attr('data-name', map[field][0]); 
     $('.bound[name='+field+']').attr('data-hidden', map[field][1]); 
     $('.bound[name='+field+']').change(function() { 
      if ($(this).val() == this.attr('data-name')) 
      { 
       $('.hidden[name='+this.attr('data-hidden')+']').show(); 
      } 
     }); 
    } 
}