声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版。

这篇文章我们将改造 FineUIMvc 默认的通知对话框,使得同时显示多个也不会重叠。并提前出一个公共的JS文件,供大家使用。

FineUIMvc 的通知对话框

FineUIMvc默认的通知对话框通过 F.notify 来显示,可以在页面上的 9 个位置显示,分别对应于属性:

  1. PosotionX = Left,  PositionY = Top
  2. PosotionX = Left,  PositionY = Center
  3. PosotionX = Left,  PositionY = Bottom
  4. PosotionX = Center,  PositionY = Top
  5. PosotionX = Center,  PositionY = Center
  6. PosotionX = Center,  PositionY = Bottom
  7. PosotionX = Right,  PositionY = Top
  8. PosotionX = Right,  PositionY = Center
  9. 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

FineUIMvc随笔(7)扩展通知对话框(显示多个不重叠)的更多相关文章

  1. FineUIMvc随笔 - 动态创建表格列

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 用户需求 用户希望实现动态创建表格列,在 WebForms 中,我们通过在 Page_Init 中创建列来实现: 但是在 MVC ...

  2. FineUIMvc随笔(1)动态创建表格列

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. <FineUIMvc随笔>目录 FineUIMvc随笔(1)动态创建表格列 FineUIMvc随笔(2)怎样在控件中 ...

  3. 自行扩展 FineUIMvc 通知对话框(多个并排显示不重叠,支持最新的显示在最上方)

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 这篇文章我们将改造 FineUIMvc 默认的通知对话框,使得同时显示多个也不会重叠.并提前出一个公共的JS文件,供大家使用. ...

  4. FineUIMvc随笔(4)自定义回发参数与自定义回发

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 不能忘却的回发 在上一篇文章中,我们对FineUIMvc中的回发进行了详细描述,目的是为了告诉大家: 1. FineUIMvc中 ...

  5. FineUIMvc随笔(5)UIHelper是个什么梗?

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. UIHelper.Result 在 FineUIMvc 的每一个 HttpPost 的控制器方法里面,你都会看到 UIHelpe ...

  6. FineUIMvc随笔(6)对比WebForms和MVC中表格的数据库分页

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 通过对比WebForms和MVC中表格数据库分页代码的不同,可以对 MVC 中的数据流转有更加深入的了解. WebForms 中 ...

  7. MFC对话框显示BMP图片

    1.MFC对话框显示BMP图片我们先从简单的开始吧.先分一个类: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) ...

  8. AsyncTask 与 对话框显示 view.WindowManager$BadTokenException: Unable to add window…is not valid; is your a

    最近遇到一个奇葩的问题,好郁闷 之前也没有仔细看.问题偶尔出现一次.再去查看日志时,出现 view.WindowManager$BadTokenException: Unable to add win ...

  9. MFC 在对话框显示图片的多种方法

      我们先从简单的开始吧.先分一个类: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) 为方便说明,我们已经建好一 ...

随机推荐

  1. Apache httpd.conf配置文件主要内容解释

    1 ServerRoot 配置 ["ServerRoot" 主要用于指定Apache的安装路径,此选项参数值在安装Apache时系统会自动把Apache的路径写入.Windows安 ...

  2. [翻译]SQL Server等待事件—THREADPOOL

      前言: 本文是对SQLSkills上一篇关于SQL Server中THREADPOOL等待的博客的翻译,本文也不是完全翻译,有些地方适当加入了自己的一些认知.如有翻译不对或不好的地方,敬请指出,大 ...

  3. linux vbundle插件配置

    1.新建目录,clone源码 mkdir ~/.vim/bundle/ git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vun ...

  4. linux文件统计命令和目录统计命令

    1.统计本目录下除`./apps/myapp/migrations`的所有py文件 wc -l `find -path . -o -name '*py' ! -path "./apps/my ...

  5. Exception in thread "main" java.lang.RuntimeException: Hive metastore database is not initialized. Please use schematool (e.g. ./schematool -initSchema -dbType ...) to create the schema. If needed, do

    继上一篇Hive: Exception in thread "main" java.lang.RuntimeException: Hive metastore database i ...

  6. [20181130]control file sequential read.txt

    [20181130]control file sequential read.txt --//昨天上午探究了大量控制文件读的情况,链接:http://blog.itpub.net/267265/vie ...

  7. C# -- 交错数组的使用

    C# -- 交错数组的使用 交错数组是元素为数组的数组.交错数组元素的维度和大小可以不同.交错数组有时称为“数组的数组”. 1. 举例一:子数组是长度相同的一维数组 static void Main( ...

  8. June 11. 2018 Week 24th, Monday

    Love is the beauty of the soul. 爱是灵魂之美. From Saint Augustine. The complete version of this quote goe ...

  9. Gulp的简单使用

    我比较喜欢使用Gulp,因为简单好用! 今天的任务是:使用Gulp来压缩 jQuery源码,各输出一个压缩的和未压缩的版本 第一步:安装 cnpm install gulp --save-dev cn ...

  10. Pandas 拼接操作 数据处理

    数据分析 生成器 迭代器 装饰器 (两层传参) 单例模式() ios七层 io多路 数据分析:是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来,总结出所研究对象的内在规律 pandas的拼接操作 p ...