[jQuery]將marquee plugin封裝成User Control
需求說明
- 需要類似跑馬燈的方式,呈現一組一組的訊息。
- 訊息太長時,不要破壞版面。
- 因為訊息數量不固定,為避免訊息尚未呈現完畢即更新訊息,所以更新訊息的時間點不使用timer定時更新。而是當最後一則訊息呈現完畢後,才撈最新資料。
- 當沒有資料時,應定時檢查是否有最新訊息。
- 當只有一筆資料時,也應定時檢查是否有最新訊息。
- 為避免檢查與更新資料影響頁面,採非同步的方式處理。
- 方便各個頁面使用,將其封裝成user control,只要設定資料來源網址就可以使用。
使用的plugin
跑馬燈的呈現,是我們的一個重點,這邊我使用了Marquee jQuery Plug-in v1.0.01,效果可以參考這裡。
- 訊息長度超過div寬度,則類似跑馬燈,文字內容往左跑
- 每則訊息呈現完畢,往上翻呈現下一則訊息
- 訊息可以有分組的概念
- 呈現每一個訊息時,可以有相關的event handler callback function可以增加自己要處理的邏輯。
Sample code
-
DashBoard.ascx
<style type="text/css"> .marquee .author { display: none; } </style> <div id="marquee-author" class="marquee-author"> </div> <div id="divMarquee"> </div>
-
DashBoard.ascx.cs
public partial class Portal_UserControl_DashBoard_DashBoard : System.Web.UI.UserControl { /// <summary> /// Gets or sets the ajax data source path. /// </summary> /// <value> /// The ajax data source path. /// </value> public string AjaxDataSourcePath { get; set; } /// <summary> /// Handles the Init event of the Page control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected void Page_Init(object sender, EventArgs e) { this.IncludeJavaScript(); this.IncludeCSS(); } /// <summary> /// Includes the CSS. /// </summary> private void IncludeCSS() { HtmlGenericControl marqueeCss = this.InitStyleSheet("~/portal/css/jquery.marquee.css"); this.Page.Header.Controls.Add(marqueeCss); } /// <summary> /// Inits the style sheet. /// </summary> /// <param name="href">The href.</param> /// <returns>html control, type為css</returns> private HtmlGenericControl InitStyleSheet(string href) { HtmlGenericControl css = new HtmlGenericControl("link"); css.Attributes.Add("href", ResolveUrl(href)); css.Attributes.Add("type", "text/css"); css.Attributes.Add("rel", "stylesheet"); return css; } /// <summary> /// Includes the java script. /// </summary> private void IncludeJavaScript() { HtmlGenericControl jquery = this.InitJavaScript("~/portal/js/jquery-1.4.4.min.js"); this.Page.Header.Controls.Add(jquery); HtmlGenericControl marquee = this.InitJavaScript("~/portal/js/jquery.marquee.js"); this.Page.Header.Controls.Add(marquee); if (string.IsNullOrEmpty(this.AjaxDataSourcePath)) { ////若AjaxDataSourcePath沒有值,則設定預設路徑 this.AjaxDataSourcePath = "~/portal/UserControl/DashBoard/DashBoardWithMarquee.ashx"; } ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "DashBoradDataSource", string.Format("var dashBoardPath = '{0}';", ResolveUrl(this.AjaxDataSourcePath)), true); HtmlGenericControl dashBoard = this.InitJavaScript("~/portal/UserControl/DashBoard/DashBoard.js"); this.Page.Header.Controls.Add(dashBoard); } /// <summary> /// Inits the java script. /// </summary> /// <param name="src">The SRC.</param> /// <returns>html control, type為javascript</returns> private HtmlGenericControl InitJavaScript(string src) { HtmlGenericControl script = new HtmlGenericControl("script"); script.Attributes.Add("src", ResolveUrl(src)); script.Attributes.Add("type", "text/javascript"); return script; } }
-
DashBoardWithMarquee.ashx
將要呈現的訊息組合成<ul>與<li>,這邊的例子是用Dictionary<string, List<string>>來存放各群組的訊息內容。
public class DashBoardWithMarquee : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; var result = this.GetMessage(); context.Response.Write(result); } private string GetMessage() { var messageCollection = new Dictionary<string, List<string>>(); var now = DateTime.Now.ToString(); messageCollection.Add("訊息群組1", new List<string> { now, "訊息1", "訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長訊息2特別長", "訊息3" }); messageCollection.Add("訊息群組2", new List<string> { now, "訊息A", "訊息B" }); var divSb = new System.Text.StringBuilder(); foreach (var item in messageCollection) { var divContent = new System.Text.StringBuilder(); foreach (var message in item.Value) { string liValue = string.Format(@"<li><span class=""author"">{0} :</span>{1}</li>", item.Key, message); divSb.AppendLine(liValue); } } string result = string.Empty; if (messageCollection.Count != 0) { result = string.Format(@"<ul id=""marquee"" class=""marquee"">{0}</ul>", divSb.ToString()); } return result; } public bool IsReusable { get { return false; } } }
-
DashBoard.js
var rotateTime = 10000; $(document).ready(function () { MarqueeBinding(); //每10秒檢查一次是否需要重撈資料 window.setInterval(checkMarquee, rotateTime); }); function checkMarquee() { var liLength = $('#divMarquee').find('li').length; //當裡面的<li>個數為0或1的時候,需重新撈資料 if (liLength < 2) { MarqueeBinding(); } } function MarqueeBinding() { //重撈資料,先將div內容清空 $('#divMarquee').html(''); //透過$(selector).load()來非同步的呼叫.ashx更新資料 $('#divMarquee').load(dashBoardPath, "", function (d) { if (d.length == 0) { $('#marquee-author').html(''); } else { var $liCounter; $("#marquee").marquee({ //因為每到最後一個<li>呈現結束的時候,要重新撈資料,所以只需要loop一次 loop: 1 , init: function ($marquee, options) { $liCounter = 1; if ($marquee.is("#marquee")) options.yScroll = "bottom"; } , beforeshow: function ($marquee, $li) { var $author = $li.find(".author"); if ($author.length) { $("#marquee-author").html("<span style='display:none;'>" + $author.html() + "</span>").find("> span").fadeIn(850); } } , show: function () { } , aftershow: function ($marquee, $li) { var liLength = $marquee.find('li').length; //當<li>不只一個,且現在show的為最後一個<li>時,則重新繫結資料 if ($liCounter > 1 && $liCounter == liLength) { MarqueeBinding(); } else { var $author = $li.find(".author"); if ($author.length) $("#marquee-author").find("> span").fadeOut(250); } $liCounter++; } }); } }); }
只要直接在.aspx上,拉進這個User Control,設定好資料來源的url,就可以使用了。
結論
相關重點整理:
- marquee plugin的使用,將<ul>與<li>以跑馬燈方式呈現。透過相關event的callback function來控制畫面呈現方式與資料處理,在最後一個<li>呈現後,遞迴呼叫自己這個初始化跑馬燈的function。
- 透過$(selector).load()來非同步讀取資料與更新selector內的html,重新啟動(初始化)跑馬燈。
- 透過window.setInterval來定時檢查是否需要撈最新的資料。
Source code :MarqueeSample.zip
blog 與課程更新內容,請前往新站位置:http://tdd.best/