2013-06-19 77 views
2

我正在嘗試創建模式彈出式窗口(例如,對於是/否確認),以便在彈出窗口被回答之前代碼不會繼續執行。我知道推薦的方法是爲每個按鈕(菜單項)添加回調,但當菜單是循環的一部分時,此方法會出現問題,其中一個結果可能是循環中的「中斷」,而不是函數呼叫。 無論如何,我想出了代碼在這裏,使用一個jQuery 1.3彈出小窗口:試圖製作模式彈出式菜單

var $popUp; 
var popupResult; 
function wait() 
{ 
    if (popupResult == null) { 
     setTimeout(wait, 100); 
    } 
    else 
     return; 
} 

function CreatePopupMenu(title) 
{ 
    popupResult = null; 
    // for safety, timeout the popup if it isn't answered 
    setTimeout(function(){ popupResult = false; }, 3000); 
    $popUp = $("<div/>").popup({ 
     dismissible: false, 
     theme: "c", 
     afteropen: function() { 
      while (popupResult == null) 
       wait(); 
     } 
    }).on("popupafterclose", function() 
    { 
     $(this).remove(); 
    }); 
    $("<h4/>", { text: title }).appendTo($popUp); 
} 

的問題是,彈出實際上並沒有出現,代碼運行直入「afteropen」回調。如果彈出窗口沒有出現,用戶不能使用按鈕來設置'popupResult',所以等待會一直持續。如果我刪除'afteropen'回調,彈出窗口按預期顯示,但是現在'popupResult'仍然爲空(它將通過在打開之前附加到菜單上的按鈕上的回調來設置)。 一個附屬問題是,爲什麼我的'離開子句'有更長的超時時間?

+0

您使用的是什麼彈出式庫/小部件? – hamstu

+0

請注意,在javaScript中使用double等於運算符'!popupResult == false == null == undefined == 0 ==''== NaN'。簡單地使用not運算符,對於三重等於的特殊檢查,例如'null!== false'。 – metadings

+0

我正在使用jquery mobile 1.3.1。關於==運算符的好處,但這只是一個簡單的例子 - 我會改變它,以便popupresult可以是0,1,2等,這取決於按下哪個按鈕 – quilkin

回答

0

你可以使用JQuery UI嗎?它附帶它自己的模態對話框。

http://jqueryui.com/dialog/#modal

+0

請參閱我對@hamstu上面的答案的評論,jquery Ui對話框還依賴於按鈕回調的回調,並且它們都會繼續處理超出彈出窗口的位置 - 它們不會等待答案,因此不是真正的模式(無論如何,我的意思是這個詞) – quilkin

1

變化

afteropen: function() { 
    while (popupResult == null) 
     wait(); 
} 

afteropen: wait 

afteropen: function() { wait(); } 

目前你無盡做wait和永遠不會離開循環。這也創造了無限的超時。

使用改變你正在做的一次「等待」 - 這並重新setTimeout的,直到popupResult沒有更多的不!


BTW:此行可能不會做,甚至干涉你的意圖。如果這是由瀏覽器在用戶選擇答案和下一個「等待」超時之間執行的 - 這會重置用戶的更改。

setTimeout(function(){ popupResult = false; }, 3000); 

更好地保存在waitTimeout wait

var waitTimeout; 

function wait() { 
    if (!popupResult) { 
     waitTimeout = setTimeout(wait, 100); 
    } 
} 

所以,你可以做clearTimeout和自動關閉彈出:

setTimeout(function() { 
    if (waitTimeout) { 
     clearTimeout(waitTimeout); 
     waitTimeout = undefined; 
    } 
    popupResult = undefined; 
    $popUp.close(); 
}, 3000); 
+0

刪除' while(popupResult == null)'只是使返回的結果爲空;它不會等待用戶選擇任何內容。雖然我只是真的把這個問題作爲解決原始問題的一部分,但關於30000超時的「退出條款」還是很好的一點。 – quilkin

+0

我不明白你現在在哪裏設置「對話框的返回值」(我不是真正熟悉jquery mobile;))但是while(popupResult == null)'沒有設置或返回任何東西都會循環不休,阻止任何進一步的執行 - javaScript是單線程的 - 所以setTimeout會創建超時,但這些事情直到你離開時纔會發生。 – metadings

2

正如所提到的,你也許可以找到一個預爲您的問題提供解決方案;有噸jQuery的模態彈出式廣告和包裝盒外面的(谷歌是你的朋友。)這就是說,我至少可以看到一個問題:

$popUp = $("<div/>").popup({ 
    dismissible: false, 
    theme: "c", 
    afteropen: function() { 
    /* while (popupResult == null) */ // <-- REMOVE THIS LINE 
    wait(); 
    } 
}) 

while循環是不必要的。事實上,在這種情況下,你很少要使用while循環;你基本上開始了一個無限循環(因爲它會阻止其他代碼的執行,瀏覽器渲染等)。嘗試刪除它,並且您的代碼應該按預期工作。 (我沒有測試過這個。)


一個更好的方式來做到這將是結構化你的彈出窗口中的HTML像這樣:(您可以創建這個代碼jQuery中也類似於你的例子)

<div class='popup' id='myPopup'> 
    <h2>Popup Title</h2> 
    <a href='#' class='action' data-action='close'>Close</a> 
    <a href='#' class='action' data-action='other'>Press Me!</a> 
</div> 

,那麼你會只需將事件處理程序(即回調)附加到鏈接/按鈕即可。

$('.popup a.action').on('click', function(event) { 
    var action = $(this).data('action'); 
    // Do something... (Close popup, etc.) 
}); 

我希望這是有道理的。

+0

是的,有很多可用的模式彈出窗口,但它們都需要每個選定項目的回調,並且它們都允許處理在用戶回答之前繼續彈出窗口。例如,我們不能把一個'break'(作爲一個循環)作爲回調。同樣在我的情況下(並且通常情況下)在菜單彈出後還有進一步的處理,並且處理取決於彈出的結果。 – quilkin

+1

有沒有辦法暫停執行,並等待你問;這在JavaScript中是不可能的,你**有**使用回調,正如我演示的。如果您的代碼取決於模態的結果,則將其放入不同的函數中,並在用戶做出選擇時調用該函數。 – hamstu

+1

好的,謝謝,我現在接受我正在嘗試的是不可能的;我只需要習慣這種單線程(經過多年的.NET編碼後很困難!)並重構了我的大部分代碼。 ... – quilkin