2012/12/18

[WhatsOld] the transit from window.open to jQuery UI Dialog : 從 window.open 改用 jQuery UI 的 Dialog

在工作時製作或幫忙維護的後台管理系統之中,大概有八成的另開視窗功能是使用 window.open 開啟的,像這樣



不過早在兩年前就已經流行把另開視窗或是確認對話盒的功能改成在網頁內模擬出來,例如 jQuery UI 的 Dialog,像這樣



其實兩年前我就想試試把另開視窗的功能改用 jQuery UI Dialog 實作看看,結果想了兩年還在用想的 Orz ... (教:為什麼想了兩年?我:報告教官!沒有理由!教:很好,俯地挺身二十下預備~~開始!)

呼~來改吧!

先,來看看原本的另開視窗是怎麼寫的。

Main.aspx,
有一顆 html 按鈕透過 popWin 這個函式來開啟 Sub.aspx,並且留一個會變成 html 隱藏項目 <input type="hidden"> 的 HiddenField: hidParam 在網頁中 /
<form id="form1" runat="server">
<div>
    <input type="button" onclick="popWin('Sub.aspx', 500, 300);" value="編輯" /><br />
    <asp:Literal ID="ltrContent" runat="server"></asp:Literal>
</div>
<asp:HiddenField ID="hidParam" runat="server" Value="" />
</form>
popWin 內容就是使用 window.open /
function popWin(link, w, h) {
    var fw = (screen.width - w) / 2;
    var fh = (screen.height - h) / 2;
    window.open(link, '', 'scrollbars=1, width=' + w + ', height=' + h + ', top=' + fh + ', left=' + fw);
}

Main.aspx.cs 先加個預設內容 /
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ltrContent.Text = @"<div class='initState'>這是一個風和日麗的清晨。</div>";
    }
}

這時執行程式,長這樣,

按下「編輯」時,要開啟的 Sub.aspx 內容如下,

Sub.aspx /
<form id="form1" runat="server">
<div>
    等一會兒將發生什麼事?<asp:DropDownList ID="ddlAnswers" runat="server"></asp:DropDownList>
    <br />
    <asp:Button ID="btnConfirm" runat="server" Text="決定了" 
        onclick="btnConfirm_Click" />
      <input type="button" onclick="window.close();" value="關閉" />
</div>
</form>

Sub.aspx.cs,
在實際工作中,像 ddlAnswers 這樣的下拉式選單內容很可能是從資料庫讀取出來的,btnConfirm_Click 也應該會需要執行儲存資料到資料庫的動作,這裡用隨便打的假資料帶過。重點是,按下 btnConfirm 確認後,在此利用 window.opener 找出上一層,也就是 Main.aspx 裡面的 hidParam 並改寫 hidParam 的值以後,透過 form1.submit() 觸發 Main.aspx 的 PostBack,最後把自己這個視窗關掉 /
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ddlAnswers.Items.Add(new ListItem("不想選", ""));
        ddlAnswers.Items.Add(new ListItem("吹個風吧", "1"));
        ddlAnswers.Items.Add(new ListItem("快轉時間", "2"));
    }
}
protected void btnConfirm_Click(object sender, EventArgs e)
{
    string scripts = "";
    scripts += "window.opener.document.getElementById('hidParam').value='" + ddlAnswers.SelectedValue + "';";
    scripts += "window.opener.document.forms[0].submit(); window.close();";
    ClientScript.RegisterStartupScript(GetType(), "", scripts, true);
}


按下 btnConfirm 之後,Main.aspx.cs 再加一點東西,就是在 Server 上判斷 hidParam.Value 的內容之後做回應,所有動作就這麼接起來啦~

Main.aspx.cs 改;這部分在實際工作中,應該也是需要去資料庫讀取資料來完成重新整理畫面的目的,這裡繼續假資料帶過 /
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ltrContent.Text = @"<div class='initState'>這是一個風和日麗的清晨。</div>";
    }
    else
    {
        switch (hidParam.Value)
        {
            case "1":
                ltrContent.Text = @"<div class='resultState'>突然間,大風狂吹。</div>";
                break;
            case "2":
                ltrContent.Text = @"<div class='resultState'>一下子,就到了半夜。</div>";
                break;
            default:
                ltrContent.Text = @"<div class='resultState'>沒有任何事情發生。</div>";
                break;
        }
        hidParam.Value = "";
    }
}

(時間過了一個小時半 ... 我寫得真慢 ... 我明天不想再遲到阿~~加油!)

知道本來的原理之後,接著來看看 jQueryUI 的 Dialog 怎麽動的吧 ... 那個 ... 請自行看官網 XD 我拿 Animation 那個範例當參考 連結

都了解了兩邊的原理後,動手改吧。

一步,另外做一個 Main.aspx,改名為 MainWithJqueryUI.aspx。

MainWithJqueryUI.aspx,
來吧,先把 jQuery UI 需要的 css 和 js 加進來 /
<link rel="Stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
再來,加上需要的 div 區塊,也就是對話盒主體,裡面我放個 iframe,準備用來裝 Sub.aspx /
<div id="dialog" title="裝個iframe">
    <iframe id="popupContainer" frameborder="0"></iframe>
</div>
再用 jQuery 把剛剛的 div 宣告為 jQuery UI 的 dialog /
$(function () {
    $("#dialog").dialog({
        autoOpen: false,
        modal: true,
        position: {my:"center", at:"center", of:window },
        show: "fade",
        hide: "fade"
    });
});
再這一步的最後,把 popWin 內容改一下,效果就會不一樣啦~
function popWin(link, w, h) {
    $("#popupContainer")
        .attr("src", link)
        .attr("width", w)
        .attr("height", h);
    $("#dialog")
        .dialog("option", "width", w+50)
        .dialog("option", "height", h+80)
        .dialog("open");
}

再一次的按下「編輯」鈕,

不過,Sub.aspx 同樣的 btnConfirm 沒有反應了,(我想睡覺阿 ...囧rz)
原來,這個時候,window.opener 是沒東西的,google 了一下解決方式,要改用 window.parent ,所以 ... 繼續!

二步,當 Sub.aspx 按下 btnConfirm 時,如果找不到 window.opener 就改用 window.parent。

Sub.aspx.cs /
protected void btnConfirm_Click(object sender, EventArgs e)
{
    string scripts = "if(window.opener) {";
    scripts += "window.opener.document.getElementById('hidParam').value='" + ddlAnswers.SelectedValue + "';";
    scripts += "window.opener.document.forms[0].submit(); window.close();";
    scripts += "} ";
    scripts += "else if(window.parent) {";
    scripts += "window.parent.document.getElementById('hidParam').value='" + ddlAnswers.SelectedValue + "';";
    scripts += "window.parent.document.forms[0].submit(); ";
    scripts += "} ";
    ClientScript.RegisterStartupScript(GetType(), "", scripts, true);
}
終於~

附上我修改後的程式碼 連結
晚安~

沒有留言:

張貼留言