宣告:FineUIMvc(基礎版)是免費軟體,本系列文章適用於基礎版。
這篇文章我們將改造 FineUIMvc 預設的通知對話方塊,使得同時顯示多個也不會重疊。並提前出一個公共的JS檔案,供大家使用。
FineUIMvc 的通知對話方塊
FineUIMvc預設的通知對話方塊透過 F.notify 來顯示,可以在頁面上的 9 個位置顯示,分別對應於屬性:
- PosotionX = Left, PositionY = Top
- PosotionX = Left, PositionY = Center
- PosotionX = Left, PositionY = Bottom
- PosotionX = Center, PositionY = Top
- PosotionX = Center, PositionY = Center
- PosotionX = Center, PositionY = Bottom
- PosotionX = Right, PositionY = Top
- PosotionX = Right, PositionY = Center
- PosotionX = Right, PositionY = Bottom
我們有專門的示例頁面來演示相應的效果:
http://fineui.com/demo_mvc/#/demo_mvc/Message/Notify
美中不足的時,如果同時有多個通知對話方塊時,就會出現重疊,如下所示:
自定義通知對話方塊分組
為了解決這個問題,我們需要對 F.notify 進行一個簡單的封裝,得到的效果如下圖所示:
呼叫這個封裝好的函式非常簡單,來看下這個頁面的實現程式碼:
@(F.Button() .Text("彈出通知對話方塊(多次點選)") .ID("btnOperation1") .Listener("click", "onOperation1Click") )
<script src="~/res/js/notify_group.js"></script> <script type="text/javascript"> var _orderNumber = 0; function onOperation1Click(event) { // 建立一個訊息對話方塊例項 var displayTime = 2000 + Math.random() * 10000; var allMessageIcons = ['information', 'warning', 'question', 'error', 'success']; showNotifyGroup({ message: '這是第 <strong>' + _orderNumber + '</strong> 條提示資訊,顯示' + Math.floor(displayTime / 1000) + '秒', messageIcon: allMessageIcons[_orderNumber % allMessageIcons.length], header: false, displayMilliseconds: displayTime }); _orderNumber++; } </script>
這裡面實際執行的函式就是 showNotifyGroup,需要傳入的引數如下:
1. message:顯示的訊息正文
2. messgeIcon:訊息正文前面的圖示
3. displayMilliseconds:顯示的毫秒數(然後會自動消失)
其實,我們可以傳入 F.notify 的任何引數,因為 showNotifyGroup 內部也是對 F.notify 的呼叫,只不過做了一定的擴充套件。
下面就來看下 showNotifyGroup 函式的具體實現:
// 通知對話方塊分組 (function () { // _notifySpace: 訊息框之間的間距 // _notifies: 存放當前正在顯示的對話方塊列表 var _orderNumber = 1, _notifySpace = 5, _notifies = []; // 對話方塊關閉處理函式 function onNotifyHide() { var notify = this; var notifyHeight = notify.el.outerHeight(true) + _notifySpace; var notifyIndex = $.inArray(notify, _notifies); _notifies.splice(notifyIndex, 1); var count = _notifies.length; if (count) { for (var i = notifyIndex; i < count; i++) { var item = _notifies[i]; item.top -= notifyHeight; item.el.animate({ 'top': item.top }); } // 按照 notify.top 重新排序 _notifies.sort(function (a, b) { return a.top - b.top; }); } } // 獲取對話方塊元素的top屬性 function calcNotifyTop() { var top = _notifySpace; if (_notifies.length) { var lastNotify = _notifies[_notifies.length - 1]; top += lastNotify.top + lastNotify.el.outerHeight(true); } return top; } // 公開方法 window.showNotifyGroup = function (options) { // 建立一個訊息對話方塊例項 $.extend(options, { top: calcNotifyTop(), positionX: 'right', listeners: { hide: onNotifyHide } }); _notifies.push(F.notify(options)); } })();
首先看下公開的 showNotifyGroup 方法的實現,需要傳入 F.notify 的有三個引數:
1. top:訊息框左上角的垂直座標,由於最新的在最後面顯示,所以每次都要計算這個位置
2. posotionX:固定為 right,也就是在頁面右側顯示
3. hide:訊息框隱藏時的處理函式,裡面主要是 3 個處理:
------3.1:從訊息框佇列中刪除需要隱藏的訊息框
------3.2:改變正在顯示的所有訊息框的 top 屬性
------3.3:按照 top 由小到大的順序排序
自定義通知對話方塊分組(最新的顯示在最上方)
上面實現的效果是最新的顯示在最下方,程式碼還比較簡潔。而如果要求最新的顯示在最上方,則面臨對動畫效果的控制:
1. 顯示新訊息框時,需要將現有的所有訊息框下移,並且等到大家都完成下移動作後,再顯示新訊息框
2. 顯示新訊息框時,有可能正在進行下移動畫效果,並且上一個訊息框還沒顯示(正在等動畫完成),此時需要立即終止所有動畫,並顯示上一個訊息框,之後再處理新的訊息框
3. 某個訊息框隱藏時,也有可能正在進行下移動畫,此時也要做相同的處理
所以,雖然封裝的程式碼邏輯複雜了,不過呼叫方法依然沒變,效果也是很讚的:
這個示例的呼叫程式碼很簡單,和上例相比,只多了一個 true 的引數:
<script src="~/res/js/notify_group.js"></script> <script type="text/javascript"> var _orderNumber = 0; function onOperation1Click(event) { // 建立一個訊息對話方塊例項 var displayTime = 2000 + Math.random() * 10000; var allMessageIcons = ['information', 'warning', 'question', 'error', 'success']; showNotifyGroup({ message: '這是第 <strong>' + _orderNumber + '</strong> 條提示資訊,顯示' + Math.floor(displayTime / 1000) + '秒', messageIcon: allMessageIcons[_orderNumber % allMessageIcons.length], header: false, displayMilliseconds: displayTime }, true); _orderNumber++; } </script>
現在來看下完整的 notify_group.js 的程式碼:
// 通知對話方塊分組 (function () { // _notifySpace: 訊息框之間的間距 // _notifies: 存放當前正在顯示的對話方塊列表 var _orderNumber = 1, _notifySpace = 5, _notifies = []; // 對話方塊關閉處理函式 function onNotifyHide() { // 先清空之前尚未完成的動畫 clearNotifiesAnimation(); var notify = this; var notifyHeight = notify.el.outerHeight(true) + _notifySpace; var notifyIndex = $.inArray(notify, _notifies); _notifies.splice(notifyIndex, 1); var count = _notifies.length; if (count) { for (var i = notifyIndex; i < count; i++) { var item = _notifies[i]; item.top -= notifyHeight; item.el.animate({ 'top': item.top }); } // 按照 notify.top 重新排序 _notifies.sort(function (a, b) { return a.top - b.top; }); } } // 所有對話方塊下移 function moveNotifiesDown(newNotify, fn) { // 先清空之前尚未完成的動畫 clearNotifiesAnimation(); var count = _notifies.length, finished = 0; if (!count) { fn.apply(window); return; } var notifyHeight = newNotify.el.outerHeight(true) + _notifySpace; for (var i = 0; i < count; i++) { var item = _notifies[i]; item.top += notifyHeight; item.el.animate({ 'top': item.top }, function () { // 動畫完成後執行的函式 finished++; if (finished >= count) { fn.apply(window); } }); } } // 停止動畫,並回撥 function clearNotifiesAnimation() { var count = _notifies.length; if (count) { for (var i = 0; i < count; i++) { var item = _notifies[i]; var itemEl = item.el; if (itemEl.is(":animated")) { itemEl.stop(false, true); } } } } // 獲取對話方塊元素的top屬性 function calcNotifyTop() { var top = _notifySpace; if (_notifies.length) { var lastNotify = _notifies[_notifies.length - 1]; top += lastNotify.top + lastNotify.el.outerHeight(true); } return top; } // 公開方法 window.showNotifyGroup = function (options, newestOnTop) { // 建立一個訊息對話方塊例項 $.extend(options, { positionX: 'right', listeners: { hide: onNotifyHide } }); if (newestOnTop) { // 最新的顯示在最上方,需要先隱藏,等 moveNotifiesDown 之後再顯示 options.hidden = true; options.top = _notifySpace; } else { options.top = calcNotifyTop(); } var notify = F.notify(options); if (newestOnTop) { moveNotifiesDown(notify, function () { notify.show(); }); _notifies.splice(0, 0, notify); } else { _notifies.push(notify); } } })();
如果你也想要這樣的效果,很簡單,把 notify_group.js 丟到你的專案中,直接呼叫 showNotifyGroup 函式即可!
小結
雖然本篇講的是 FineUIMvc ,其實是對內部 JavaScript 程式碼的一個簡單擴充套件和封裝,由此可見 FineUIMvc 前端庫的靈活性。我們可以直接把 notify_group.js 丟到專案中,呼叫 showNotifyGroup 函式即可實現上述效果。你也可以自行擴充套件來在頁面的不同地方顯示通知對話方塊,實現更復雜的動畫效果。
《FineUIMvc隨筆》目錄:http://www.cnblogs.com/sanshi/p/6473592.html