[ASP.NET]Show Information Message using jQuery plug-in: humanizedMessage

  • 10976
  • 0
  • 2009-11-26

[ASP.NET]Show Information Message using jQuery plug-in: humanizedMessage

前言

在之前的專案一直有個東西很想改掉,就是information message的顯示,例如「新增成功」、「刪除成功」等等...
訊息的type其實就跟log差不多,基本上分為三種,

  1. Information
  2. Warning
  3. Confirm

Warning與Confirm的部分比較簡單,因為javascript就有提供alert()與confirm()的function。
但是如果information也使用alert()來做,
一來user操作過程明明沒犯錯,卻要他們還用滑鼠去點一下messageBox,是比較不friendly的,
二來比較無法區分出到底什麼是warning訊息。

 Survey Solution

有鑑於此,之前survey過幾個解決方案,
讓我最心動的是一個用RoR寫的plug-in,是不是Mootool我也忘了,也找不到了。
(為了要show一個message,要整個專案的人學Ruby on Rails我應該會被釘在牆上)
最貼近需求的,應該是[自製元件] MsnMessageBox MSN訊息通知控制項
但是該元件還是有著不少問題,而且說真的,我自己想要的樣子不是這樣。

後來就在jQuery的世界裡,找到了一個自己覺得還不錯看,也還不錯用的plug-in:Humanized Messages for jQuery
功能其實很簡單,用jQuery將code附加在特定的事件裡執行,畫面會浮出訊息,時間到會自動消失,
另外一個很貼心的設計是有message log。
讓我很欣賞的是這個plug-in的code不長,又寫的很漂亮,應用上又相當簡單,調整樣式、位置又只需要調css檔案,
相當適合我這種對jQuery還沒啥經驗,加上又是CSS白癡的人。

改善

原本的Humanized Message,是黑色的而且在畫面上方,太死氣沈沈不適合現在的台灣,
所以希望可以把訊息放在右下角,溫暖一點的顏色,順便瞭解一下這個plug-in的結構。
另一個最大的不同就是,原本的只有供client端使用,
而我希望可以在server端搭配resource檔來結合操作與訊息,比較麻煩的就是postback後message log會被清空。
不過這也沒啥好麻煩的,postback記值嘛…這入學考就考過了,一個viewstate就解決了。
順手把message log的順序調整了一下,讓越後面的操作,呈現在越上面,再加上記錄時間,我想整個user不愛上我都很難。

進化

為了讓不懂javascript、jQuery、Css、甚至html的工讀生也能快速使用,
小的只好把這功能封裝到BasePage裡面,原本在猶豫要做在MasterPage還是BasePage,後來還是決定做在BasePage裡。
因為之前專案的經驗,MasterPage太肥、太冗重,導致每一頁都很慢,
而且並不一定每一頁都要用到jquery.js,或是用到message (當然大部分還是有)。
所以決定在呼叫show message時,才動態載入js、css和註冊js、執行js。
沒用到時,畫面就跟小白豬一樣乾乾淨淨的...

Step by step

有興趣的可以先上去humanized messages網站下載source code:http://code.google.com/p/humanmsg/
我的範例程式碼(包括使用BasePage和直接在頁面引用js)Source Code:humanizedMessageSample.rar

下載完了,我們先打開humanmsg.css,


.humanMsg {
    font: normal 20px/50px Helvetica, Arial, Sans-Serif;
    letter-spacing: -1px;
    position: fixed;
    top: 85%;
    left: 50%;
    width: 50%;
    color: white;
    background-color: #ff6500;
    text-align: center; 
    display: none;
    opacity: 0;
    z-index: 100000;
}

這一段就是訊息本身的css,我改了兩個地方,

  1. top:85%,因為我希望訊息出現在頁面的下方
  2. background-color: #ff6500,原本是black,現在改成橘色

訊息靠右的部分因為寬度佔了50%,所以使用left:50%即可。


#humanMsgLog p {
    position: relative;
    left: 90%;
    width: 200px;
    margin: 0;
    margin-left: -100px;
    padding: 0 10px;
    line-height: 20px;
    background: #ff6500;
    text-align: center;
    white-space: pre;
    cursor: pointer;
    }

 

 

 

 


#humanMsgLog p:hover {
    background: #ff6500;
    }

 

 

 

 

接下來是Message log的顏色,我也改成橘色,所以background都改成#ff6500。
底下的#humanMsgLog ul {}與#humanMsgLog ul li {}則是message log的css樣式,有興趣的請自行調整。
我們來看一下畫面:

橘色訊息

Log的樣子

msgLog

接著來說明一下js修改的部分,首先打開humanmsg.js。


    //modified by 91, 增加參數msg2為本頁歷次log
    displayMsg: function(msg,msg2) {
        if (msg == '')
            return;

        clearTimeout(humanMsg.t2);

        // Inject message
        jQuery('#'+humanMsg.msgID+' p').html(msg)
    
        // Show message
        jQuery('#'+humanMsg.msgID+'').show().animate({ opacity: humanMsg.msgOpacity}, 200, function() {
            jQuery('#'+humanMsg.logID)                
                .show().children('ul').prepend('<li>'+msg2+'</li>')    // Prepend message to log                               
                .children('li:first').slideDown(200)                // Slide it down
        
            if ( jQuery('#'+humanMsg.logID+' ul').css('display') == 'none') {
                jQuery('#'+humanMsg.logID+' p').animate({ bottom: 40 }, 200, 'linear', function() {
                    jQuery(this).animate({ bottom: 0 }, 300, 'easeOutBounce', function() { jQuery(this).css({ bottom: 0 }) })
                })
            }
            
        })
        
    
        // Watch for mouse & keyboard in .5s
        humanMsg.t1 = setTimeout("humanMsg.bindEvents()", 700)
        // Remove message after 5s
        humanMsg.t2 = setTimeout("humanMsg.removeMsg()", 5000)
    },

其實也沒改了啥,我只是把displayMsg的參數增加了一個,因為原本的訊息是抓到msg,持續Prepend到message log中,
但現在我的資料處理是在server端,postback之後,message log會被清空重新Render,所以我需要透過另外一個參數來記log,
也就是jQuery('#'+humanMsg.logID) .show().children('ul').prepend('<li>'+msg2+'</li>') // Prepend message to log  這一段。
如果一樣是只在client端動作,則只需要把兩個參數都用msg傳入即可。
實際呼叫顯示訊息的js碼,則如下所示:


        jQuery(document).ready(function () {
            humanMsg.displayMsg(message,mes2);
        }) 

 

 

 

不論是在server端,client端,只要執行這一段js,就可以顯示想要的訊息。
(這一段在我的BasePage裡面也是動態註冊的。)
如果是要註冊在某個事件上的,則可以參考原範例的寫法,例如:


jQuery('a.showmessage').click(function() {
            humanMsg.displayMsg('<strong>Success:</strong> <span class="indent">You clicked \''+jQuery(this).text()+'\'</span>');
            return false;
        })

 

 

 

 

這樣的寫法就是,當頁面上<a>的class為showmessage時,click事件會觸發humanMsg.displayMsg()。
以上就是該plug-in基本的說明。 

接下來講一下我的範例,BasePage.cs程式碼如下:

/// <summary>
/// BasePage 的摘要描述
/// </summary>
public class BasePage: System.Web.UI.Page
{
        #region Fields (2)  const string jQuery = "jQuery";
    const string showMsg = "ShowMessage";

        #endregion Fields  #region Constructors (1)  public BasePage()
    {
        //
        // TODO: 在此加入建構函式的程式碼
        //
    }

        #endregion Constructors  #region Methods (4)  // Protected Methods (3) 

    /// <summary>
    /// Getmessages the specified Message id.
    /// </summary>
    /// <param name="MsgId">The Message id.</param>
    /// <returns></returns>
    protected string Getmessage(string MsgId)
    {
        return Resources.Message.ResourceManager.GetString(MsgId);
    }

    /// <summary>
    /// Registers the startup JS.
    /// </summary>
    /// <param name="RegisterName">Name of the register.</param>
    /// <param name="JS">The JS.</param>
    protected void RegisterStartupJS(string RegisterName,string JS)
    {
        string wholeJS = "<SCRIPT language=\"JavaScript\"  type=\"text/javascript\" >"+JS+"</SCRIPT>";

        if (ExistSM())
        { ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), RegisterName, wholeJS, false); }
        else
        { Page.ClientScript.RegisterStartupScript(Page.GetType(), RegisterName, wholeJS);  }
        
    }

    /// <summary>
    /// Shows the information message.
    /// </summary>
    /// <param name="info">The information message.</param>
    protected void ShowMessage(string info)
    {

        HtmlGenericControl objLink = new HtmlGenericControl("link");
        objLink.Attributes.Add("rel", "stylesheet");
        objLink.Attributes.Add("href", "humanmsg.css");
        objLink.Attributes.Add("type", "text/css");
        this.Page.Header.Controls.Add(objLink);

        HtmlGenericControl objjQuery = new HtmlGenericControl("script");
        objjQuery.Attributes.Add("language", "javascript");
        objjQuery.Attributes.Add("src", "jquery.js");
        this.Page.Header.Controls.Add(objjQuery);

        if (ExistSM())
        {
            ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), showMsg, "humanmsg.js");
        }
        else
        {
            Page.ClientScript.RegisterClientScriptInclude(showMsg, "humanmsg.js");
        }

        string showMsgFunction = @"
function ShowMe(message,mes2) {
jQuery(document).ready(function () {
humanMsg.displayMsg(message,mes2);
})
}"
; RegisterStartupJS("ShowMe", showMsgFunction); string Msglog = System.DateTime.Now.ToString("HH:mm:ss") + " &nbsp; &nbsp; &nbsp; " + info + "<br/>" + this.ViewState["MsgLog"]; this.ViewState["MsgLog"] = Msglog + this.ViewState["MsgLog"]; string js = "ShowMe('" + info + "','" + this.ViewState["MsgLog"].ToString() + "');"; RegisterStartupJS(showMsg, js); } // Private Methods (1) /// <summary> /// 檢查頁面上是否存在ScriptManager /// </summary> /// <returns></returns> private bool ExistSM() { return (ScriptManager.GetCurrent(this.Page) != null); } #endregion Methods  }

 

 

 

主要的方法只有3個

  1. Getmessage(string MsgId):傳入Message ID,到Resource裡面找出對應的訊息
  2. ShowMessage(string info):將要呈現的information message傳入,即可在頁面呈現訊息
  3. RegisterStartupJS(string RegisterName,string JS):供一般頁面可直接透過此function註冊js,其中會自行判斷畫面上是否有ScriptManager,選擇該用何種方式註冊js

ShowMessage的部分,先在PageHeader上加入引用css與相關的js。
接著撰寫實際執行的js function:ShowMe(),串好script後,交由RegisterStartupJS實際去進行註冊動作。
繼承BasePage的頁面程式碼則變得相當乾淨,
aspx:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>我是繼承BasePage的</title>    

</head>
<body>
    <form id="form1" runat="server">
    <div>       
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager> 
            <asp:RadioButtonList ID="RadioButtonList1" runat="server">
        <asp:ListItem Value="1">新增失敗</asp:ListItem>
            <asp:ListItem Value="2">新增完成</asp:ListItem>
        </asp:RadioButtonList>           
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
    </div>
    </form>
    
</body>    
</html>

 

 

 

 

.cs:

public partial class ShowByBasePage : BasePage
{
    
    protected void Button1_Click(object sender, EventArgs e)
    {
        string thisMessage = string.Empty;
        switch (this.RadioButtonList1.SelectedIndex)
        {
            case 0:
                thisMessage = this.Getmessage("10300");
                break;
            case 1:
                thisMessage = this.Getmessage("20300");
                break;
            case -1:
                thisMessage = "要選一下啊";
                break;
            default:
                thisMessage = "system error";
                break;
        }

        this.ShowMessage(thisMessage);

    }
}

 

 

 

 

大家下載完Sample code,可自行與ShowMessage.aspx做比較,會發現繼承BasePage的寫法乾淨得多,
當然重點還是在可以讓Developer直接使用,也有統一修改模組的好處。 
希望這篇文章對大家能有小小的幫助。

[註一]補充一下,這個plug-in由於IE6和IE7對CSS解讀標準不同,所以IE6格式會跑掉,IE7/8和FF3.5是OK的。


blog 與課程更新內容,請前往新站位置:http://tdd.best/