# S.Overlay

乔花

2010.09

一. 应用场景

二. 同类组件

三. 功能分析

四. 技术方案

五. Public API

六. 开发计划

七. 其它

页面上的覆盖层;

对话框层;

Popup 层;

很多很多网站上都有这类似的覆盖层效果;

    1. YUI3：http://developer.yahoo.com/yui/3/overlay/
     * new Y.Overlay(cfg);
     * 扩展于Widget, DOM基本结构包含hd,bd,ft;
     * 提供 位置相关属性(x, y, xy, centered), zIndex, align, shim(加iframe, IE6下默认true),
       constrain(固定在可视区域中间);
     * 提供 与修改对应 Attributes 的方法, 主要有 内容(WidgetStdMod),
       位置(WidgetPosition, WidgetPositionConstrain), 大小这几个方面的方法;
     * WidgetPositionAlign, 提供 Align, 支持对齐到某个元素, 整个可视区域, 特定位置上;
     * WidgetStack, 提供 Stacking, 需要zIndex和shim支持, 当有多个 Overlay 时,
       某个层获得焦点时, 将其置于顶层(对应方法 bringToTop )
     * 自定义事件 xyChange, bodyContentChange,
     * Overlay相关的Plugin, 通过 overlay.plug(XXX, cfg)/ overlay.unplug(XXX) 使用:
        # StdModIO, 提供标准的输入输出, 包含initializer, destructor, formator,
          在Overly中实例化为overlay.io;
        # Animation, 提供Overly的动画展现效果, animHidden/animVisible定义如何展现;

    2. JQuery UI, 没有提供 Overlay , 但提供了所有组件的基类 Widget, 扩展出 Dialog , 和相关组件,
       如 Draggable(拖拽), Droppable, Resizable.
     * JQuery Core + Widget + Position + Dialog, 压缩后21K;
     * Widget, 所有组件的基类, 提供 create, destroy, enable, disable等通用方法;
     * 使用 $(id).dialog();
       # 提供 定制宽高度, resize, 位置, 是否模态窗口, 可拖拽, 支持 按钮;
       # 提供的方法有 destroy, open, close, enable, disable, moveToTop, stack, 这些都是类似窗口最基本的方法;
       # 自定义事件有 open, close, beforeClose, focus, drag 等;

    3. Mootools, 由 moord 提供的 overlay.js
     * 77.3K (未压缩, 包含依赖文件), 但纯 Overlay 仅100多行;
     * new Overlay() 创建 overlay 对象;
     * 提供 创建, 删除 Overlay, 设置 颜色深浅 透明度, 功能比较简单;
     * 基于Overlay扩展的组件有 virtual box , 弹出层功能:
       # virtual-base 为基类;
       # 扩展有 virtual-box (基本的box),  virtual-ajax (请求之后显示内容), virtual-html (动态设置html内容);
       # virtual box 系列 提供 设置动画效果, 自定义样式, 位置居中等选项, 提供
         onShow, onClose, onNext, onPrev 自定义事件;

    4. Dojo 的 Dijit 提供了 digit.Dialog.
     * Dialog+DialogUnderlay 共22K, 不包含一些依赖库.
     * new dijit.Dialog(cfg);
     * 支持resize, 拖拽, 表单操作, 和其他类似, 不重复讲了;
     * 焦点的处理;

    - 数据层:
        * 内容的可自定义设置:
            # 独立设置 hd, bd, ft 三部分内容;
        * 后台请求过来的动态数据;
            # 表单数据;
            # iframe;
            # ajax;
        * 数据解析及格式化:
            # json;
            # formator;
    - 展现层:
        * 大小:
            # 设置宽度/高度;
            # resize;
        * 位置:
            # 绝对位置;
            # 相对于元素的位置;
            # zIndex, shim , stack;
        * 对齐:
            # 相对于元素的对齐;
            # 在容器或可视区域内的对齐;
        * 动画:
            # 主要是在显示/隐藏Overlay时的动画效果, 直接利用 kissy/anim, 类似 switchable 的 plugin-effect;
    - 其他:
        * 支持按钮?
        * Drag + Drop?

本质: 弹出一个层, 并且可以动态设定层位置;

- 将 Overlay 抽象处理, 只处理上面这句话的功能;

- Dialog, Popup 在 Overlay 基础上扩展, 加入自己特点;

DOM 结构

分为两种情况, 一个是已有 DOM, 一个是新建. 两者统一起来, 最终生成的 DOM 结构 如下:

    /*
     *  <div class="ks-overlay-container">
     *      <div class="ks-overlay-bd"></div>
     *  </div>
     */

当没有内容时, 不会创建 body 层;

位置计算

采用YUI3的组织方式, 利用容器元素及参考元素上各自的九个不同位置点('tl', 'tc', 'tr', 'cl', 'cc', 'cr', 'bl', 'bc', 'br')进行组合定位, 如下图所示:

Shim 和 Mask

Shim, 在 IE6 下是必备; 而 Mask 覆盖层, 通过选项设置;

Shim 和 Mask 本质上也是一致的, 都是新建一个层( div 或者 iframe ), 放在 Overlay 层 下方; 所以我们也把 Shim 和 Mask 合并起来;

S.Dialog

固定的DOM结构, 在 Overlay 基础上 增加 header, footer, close 按钮(is closeable)

    /*
     *  <div class="ks-overlay-container">
     *      <div class="ks-overlay-hd">
     *          <div class="ks-dialog-close"></div>
     *      </div>
     *      <div class="ks-overlay-bd"></div>
     *      <div class="ks-overlay-ft"></div>
     *  </div>
     */

另外, 增加 DialogManager 提供管理页面上 Dialog 的方法;

S.Popup

基本上同 Overlay, 但触发类型默认为 'mouse', 弹出层位置默认为触发元素的右侧

    var defaultConfig = {
        triggerType: 'mouse', // 触发类型, click, mouse
        align: {
            node: 'trigger',
            points: ['cr', 'ct'],
            offset: [10, 0]
        }
    };

S.Overlay

    config:
        container: null,            // Overlay 容器, 默认为 null 时, 表示新建 DOM;
        containerCls: CLS_CONTAINER,// 容器 class , 默认 class 为 'ks-overlay'
        content: undefined,         // 默认为 undefined, 不设置
        bdCls: CLS_PREFIX + 'bd',   // body class, 默认为 'ks-overlay-bd'

        trigger: null,          // 触发元素, 默认为 null 时, Overlay 动作需要另外 js 指定
        triggerType: 'click',   // 触发类型, 'mouse' or 'click', 默认为 'click'

        width: 0,               // 容器宽度
        height: 0,              // 容器高度
        zIndex: 9999,           // z-index 值

        xy: null,               // 相对 page 定位, 有效值为 [n, m]
        align: {                // 相对指定 node or viewport 定位
            node: null,         // 参考元素, falsy 值为可视区域, 'trigger' 为触发元素, 其他为指定元素
            points: [POSITION_ALIGN.CC, POSITION_ALIGN.CC],
                                // ['tl', 'tr'] 表示 overlay 的 tl 与参考节点的 tr 对齐
            offset: [0,0]       // 水平, 垂直方向上的偏移, 有效值为 [n, m]
        },
        mask: false,            // 是否显示蒙层, 默认不显示
        shim: ie6               // 是否需要垫片, IE6下默认需要

    Member:
        container               // 指向容器元素
        trigger                 // 触发元素
        config                  // 配置选项
        body                    // 容器 body 元素, 当 content 为空时,
                                //不创建 ks-overlay-bd 层, 且 body 直接指向 container
        shim                    // 垫片层, 如果选项中 shim 设置为 true

    Method:
        show()                  // 显示
        hide()                  // 隐藏
        move(x, y)              // 将 overlay 移动到指定位置上, 绝对位置
        align(node, points, offset)  // 将 overlay 定位到指定节点的特定位置上,
                                     // 如果没有指定 node, 会默认使用 config 中的 align 设置
        center()                // 将 overlay 居中到当前可视区域上
        setBody()               // 设置 body 内容

S.Dialog 增加了 header 和 footer, config 和 method 做了对应调整

    config:
        header: '',                     // header 内容
        footer: '',                     // footer 内容

        containerCls: CLS_CONTAINER,    // 设置 containerCls , 默认为 'ks-overlay ks-dialog'
        hdCls: CLS_PREFIX + 'hd',       // 设置 header 的 class , 默认为 ks-dialog-hd
        bdCls: CLS_PREFIX + 'bd',       // 设置 body 的 class , 默认为 ks-dialog-bd
        ftCls: CLS_PREFIX + 'ft',       // 设置 footer 的 class , 默认为 ks-dialog-ft
        closeBtnCls: CLS_PREFIX + 'close',      // 设置关闭按钮的 class, 默认为 ks-dialog-close

        width: 400,                     // 设置容器宽度, 默认为 400
        height: 300,                    // 设置容器高度, 默认为 300
        closable: true                  // 是否需要关闭按钮, 默认需要
    Member:
        header                          // 对话框头部的HTML元素
        footer                          // 对话框尾部的HTML元素
        manager                         // 当前 DialogManager
    Method:
        setHeader()                     // 设置 header 内容
        setFooter()                     // 设置 footer 内容

S.DialogManager

用于管理页面上所有的 Dialog , 目前提供功能较少

    Method:
        register()                    // 将 dialog 实例注册到 DialogManager 中
        hideAll()                     // 隐藏页面上所有的 dialog

S.Mask

统一了 shim 和 mask , 会在 body 最后加入 shim 层或 mask 层

    Config:
        shim: false,        // 是 shim 层还是 mask 层
        opacity: .6,        // 指定 mask 的透明度
        style: ''           // 指定样式

    Member:
        iframe              // shim 和 mask 下都会有, mask 时, 标准浏览器也用 iframe 元素生成mask
        config              // 配置选项
        layer               // mask时, 且在IE下才会有这个成员, 由于 iframe 不能设置 background,
                            // 所以添加了一 div 作为 layer , 设置透明度及背景颜色
    Method:
        show()              // 显示
        hide()              // 隐藏
        toggle()            // 切换显示/隐藏
        setSize()           // 设置宽高
        setOffset()         // 设置位置, 绝对位置

基本使用, Popup

    KISSY.ready(function(S) {

        var popup = S.Popup({
            trigger: '#link2',
            triggerType: 'mouse',
            width: 300,
            height: 200,
            containerCls: 'popup2',
            content: 'test popup',
            align: {
                node: 'trigger',
                points: ['tr', 'tl']
            }
        });

基本使用, Dialog

    KISSY.ready(function(S){
        var dialog = S.Dialog({
            trigger: '#btn4',
            containerCls: 'dialog4',
            width: 400,
            height: 300,
            title: 'this is title',
            footer: 'footer',
            content: 'content',
            mask: false
        });
        var times = 1;
        dialog.on('show', function(){
            dialog.setBody('show'+(times++));
        });

        S.Event.on('#btn5', 'click', function(e){
            dialog.manager.hideAll();
        });
    });

9月, 实现基本功能.

使用文档： http://kissyteam.github.com/kissy/docs/overlay/index.html

测试页面： http://kissyteam.github.com/kissy/src/overlay/test.html