2009-09-09 75 views
2

我有大致如下的HTML:設置顯示後的輸入元件上設置焦點:塊

<div class="hiddenClass"> // this implies display:none 
<span> 
    <input type="text" id="hiddenInput"/> 
</span> 
</div> 

和Javascript事件(在jQuery的$就一個「更迭」方法觸發()調用),需要使該div可見,然後將焦點置於控件上。例如:

this.DOMElements.divElement.className="showClass"; //a CSS class with display:block; 
this.DOMElements.hiddenInputElement.focus(); 
this.DOMElements.hiddenInputElement.select(); 

奇怪的是,此代碼僅適用於部分時間。在某些情況下(有時只有!!),focus/select命令會產生關於聚焦/選擇隱形控制的警告。控件將變爲可見,但焦點不會移動,也不會選擇文本。

我發現(有點)的溶液通過在一個單獨的函數移動聚焦/選擇代碼,並通過

this.DOMElements.divElement.className="showClass"; //a CSS class with display:block; 
setTimeout("focusinput('hidddenInput')",1); 

好了,終於我的問題的手段延遲叫它:由於JavaScript是單線程..如何在我使父div可見的時間和可以在子輸入元素上設置焦點/選擇的時間之間存在延遲?這怎麼可能是一個競爭條件?

編輯:偏偏IE8

+0

只發生在IE我認爲? –

回答

1

如果你使用jQuery,用它來顯示和設置重點:

$(".hiddenClass").fadeIn("fast", 
    function() { 
     $("#hiddenInput").focus(); 
    } 
); 

$(".hiddenClass").show(0, 
    function() { 
     $("#hiddenInput").focus(); 
    } 
); 

如果你想顯示它沒有任何淡入

基本上它正在淡化隱藏的div(如果你希望顯示一個特定的div而不是所有的具有.hiddenClass的元素,你可以用一個id替換.hiddenClass),並且一旦完成它執行回調函數以將焦點集中到輸入。

這樣你就不會嘗試給輸入焦點,直到完全顯示div後。

+0

經過測試,效果很好。但我相信jQuery fadeIn/show也在下面使用setTimeout,所以問題仍然存在,爲什麼會出現競爭條件? – Radu094

0

我不知道這裏發生了什麼,但它可能不是一個壞主意,搶你的使用div的引用,將其存儲在一個變量,然後操作那就不要每次都用getElementByID()來抓取它。

所以你上面的代碼將是:

var myDiv = document.getElementById("hiddenInput"); 
if(myDiv) 
{ 
    myDiv.className="showClass"; //a CSS class with display:block; 
    myDiv.focus(); 
    myDiv.select(); 
} 

另外:在有些情況下,瀏覽器允許旋轉起來另一個THEAD某些JavaScript函數(例如,load()函數);只是要記住:)

+0

實際上,我在課堂上既有div又有輸入元素,我只是簡單地在我的例子中提供了一些東西。如果你認爲這是相關的,我會繼續前進,並改變 – Radu094

+0

的例子,我不知道。有可能。 你是否嘗試直接改變風格而不是改變className?我仍然不確定這可能是一個競爭條件,但它絕對看起來像一個。 – neoncube

0

我以前曾遇到過這種情況。在大多數情況下,我發現通過在設置顯示器後設置超時來修復IE中的問題。不幸的是,它不是最乾淨的修復程序。

1

好的,終於我的問題:因爲JavaScript是單線程..怎麼會有一個之間的時間,我做父母的div可見,以及我可以設置焦點/選擇子輸入元素?

你剛纔已經回答你自己的問題:出現這種情況是因爲JS是單線程的;也就是說,它會阻止瀏覽器更新其渲染,直到腳本執行完畢。

所以,當你執行該代碼:

divElement.className="showClass"; 

元素的className屬性已更新,但作爲腳本仍在執行,該元素是不是立即可見重繪。因此,在執行時

hiddenInputElement.focus(); 

該元素仍然隱藏,您將收到錯誤消息。

所以,在你的第一個版本,在單個線程執行的順序是:

  1. 腳本設置的className;
  2. 腳本設置焦點;
  3. 瀏覽器拋出異常,因爲被隱藏的焦點元素;
  4. 腳本因錯誤而結束;
  5. 瀏覽器根據腳本所做的更改來更新事件,直到故障點。

當您使用setTimeout方法,順序是:

  1. 腳本設置的className;
  2. 腳本結束;
  3. 瀏覽器根據腳本所做的更改來更新內容;
  4. 超時火警;
  5. 超時腳本設置焦點,現在成功。
+0

如果你說的是真的,那麼原始代碼應該總是失敗,但它有時會起作用,所以這不可能。 – Radu094