[ASP.NET]Show Information Message using jQuery plug-in: humanizedMessage
前言
在之前的專案一直有個東西很想改掉,就是information message的顯示,例如「新增成功」、「刪除成功」等等...
訊息的type其實就跟log差不多,基本上分為三種,
- Information
- Warning
- 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,我改了兩個地方,
- top:85%,因為我希望訊息出現在頁面的下方
- 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的樣子
接著來說明一下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") + " " + 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個
- Getmessage(string MsgId):傳入Message ID,到Resource裡面找出對應的訊息
- ShowMessage(string info):將要呈現的information message傳入,即可在頁面呈現訊息
- 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/