wzp
2021-07-19 58ec6ffd2dc6a3e490e28026dd559352678a273d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
    panel
*/
 
import $ from '../util/dom-core.js'
import replaceLang from '../util/replace-lang.js'
const emptyFn = () => {}
 
// 记录已经显示 panel 的菜单
let _isCreatedPanelMenus = []
 
// 构造函数
function Panel(menu, opt) {
    this.menu = menu
    this.opt = opt
}
 
// 原型
Panel.prototype = {
    constructor: Panel,
 
    // 显示(插入DOM)
    show: function () {
        const menu = this.menu
        if (_isCreatedPanelMenus.indexOf(menu) >= 0) {
            // 该菜单已经创建了 panel 不能再创建
            return
        }
 
        const editor = menu.editor
        const $body = $('body')
        const $textContainerElem = editor.$textContainerElem
        const opt = this.opt
 
        // panel 的容器
        const $container = $('<div class="w-e-panel-container"></div>')
        const width = opt.width || 300 // 默认 300px
        $container.css('width', width + 'px')
                .css('margin-left', (0 - width)/2 + 'px')
 
        // 添加关闭按钮
        const $closeBtn = $('<i class="w-e-icon-close w-e-panel-close"></i>')
        $container.append($closeBtn)
        $closeBtn.on('click', () => {
            this.hide()
        })
 
        // 准备 tabs 容器
        const $tabTitleContainer = $('<ul class="w-e-panel-tab-title"></ul>')
        const $tabContentContainer = $('<div class="w-e-panel-tab-content"></div>')
        $container.append($tabTitleContainer).append($tabContentContainer)
 
        // 设置高度
        const height = opt.height
        if (height) {
            $tabContentContainer.css('height', height + 'px').css('overflow-y', 'auto')
        }
        
        // tabs
        const tabs = opt.tabs || []
        const tabTitleArr = []
        const tabContentArr = []
        tabs.forEach((tab, tabIndex) => {
            if (!tab) {
                return
            }
            let title = tab.title || ''
            let tpl = tab.tpl || ''
 
            // 替换多语言
            title = replaceLang(editor, title)
            tpl = replaceLang(editor, tpl)
 
            // 添加到 DOM
            const $title = $(`<li class="w-e-item">${title}</li>`)
            $tabTitleContainer.append($title)
            const $content = $(tpl)
            $tabContentContainer.append($content)
 
            // 记录到内存
            $title._index = tabIndex
            tabTitleArr.push($title)
            tabContentArr.push($content)
 
            // 设置 active 项
            if (tabIndex === 0) {
                $title._active = true
                $title.addClass('w-e-active')
            } else {
                $content.hide()
            }
 
            // 绑定 tab 的事件
            $title.on('click', e => {
                if ($title._active) {
                    return
                }
                // 隐藏所有的 tab
                tabTitleArr.forEach($title => {
                    $title._active = false
                    $title.removeClass('w-e-active')
                })
                tabContentArr.forEach($content => {
                    $content.hide()
                })
 
                // 显示当前的 tab
                $title._active = true
                $title.addClass('w-e-active')
                $content.show()
            })
        })
 
        // 绑定关闭事件
        $container.on('click', e => {
            // 点击时阻止冒泡
            e.stopPropagation()
        })
        $body.on('click', e => {
            this.hide()
        })
 
        // 添加到 DOM
        $textContainerElem.append($container)
 
        // 绑定 opt 的事件,只有添加到 DOM 之后才能绑定成功
        tabs.forEach((tab, index) => {
            if (!tab) {
                return
            }
            const events = tab.events || []
            events.forEach(event => {
                const selector = event.selector
                const type = event.type
                const fn = event.fn || emptyFn
                const $content = tabContentArr[index]
                $content.find(selector).on(type, (e) => {
                    e.stopPropagation()
                    const needToHide = fn(e)
                    // 执行完事件之后,是否要关闭 panel
                    if (needToHide) {
                        this.hide()
                    }
                })
            })
        })
 
        // focus 第一个 elem
        let $inputs = $container.find('input[type=text],textarea')
        if ($inputs.length) {
            $inputs.get(0).focus()
        }
 
        // 添加到属性
        this.$container = $container
 
        // 隐藏其他 panel
        this._hideOtherPanels()
        // 记录该 menu 已经创建了 panel
        _isCreatedPanelMenus.push(menu)
    },
 
    // 隐藏(移除DOM)
    hide: function () {
        const menu = this.menu
        const $container = this.$container
        if ($container) {
            $container.remove()
        }
 
        // 将该 menu 记录中移除
        _isCreatedPanelMenus = _isCreatedPanelMenus.filter(item => {
            if (item === menu) {
                return false
            } else {
                return true
            }
        })
    },
 
    // 一个 panel 展示时,隐藏其他 panel
    _hideOtherPanels: function () {
        if (!_isCreatedPanelMenus.length) {
            return
        }
        _isCreatedPanelMenus.forEach(menu => {
            const panel = menu.panel || {}
            if (panel.hide) {
                panel.hide()
            }
        })
    }
}
 
export default Panel