zoukankan      html  css  js  c++  java
  • FineUIMvc随笔(7)扩展通知对话框(显示多个不重叠)

    声明: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 

  • 相关阅读:
    echarts onClick执行之前都要取消绑定一次
    echarts 打包完之后体积太大解决方案。
    saga处理多个loading最少0.5s
    SVN命令详解
    netfilter/iptables原理
    交换两个变量的值,不使用第三个变量的四种法方
    linux常用命令整理
    vi技巧
    linux进程管理的常用命令
    gcc常用命令
  • 原文地址:https://www.cnblogs.com/sanshi/p/6701701.html
Copyright © 2011-2022 走看看