重构layer
parent
13665be881
commit
5c82a42bb4
|
@ -38,10 +38,7 @@
|
||||||
&.shift {
|
&.shift {
|
||||||
transition: all 0.5s ease-out;
|
transition: all 0.5s ease-out;
|
||||||
}
|
}
|
||||||
&.scale {
|
|
||||||
transform: scale(1.02);
|
|
||||||
transition: transform 0.1s linear;
|
|
||||||
}
|
|
||||||
&.blur {
|
&.blur {
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +50,7 @@
|
||||||
/* 弹层样式 */
|
/* 弹层样式 */
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
@ -62,17 +60,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
::slotted(&__input) {
|
||||||
|
flex: 1;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(&__frame) {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__ctrl {
|
&__ctrl {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
justify-content: flex-end;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
@ -156,6 +170,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import '../form/input'
|
||||||
import Drag from '../drag/core'
|
import Drag from '../drag/core'
|
||||||
|
|
||||||
import { nextTick, bind, unbind, clickOutside } from '../utils'
|
import { nextTick, bind, unbind, clickOutside } from '../utils'
|
||||||
|
@ -164,26 +179,20 @@ const LANGUAGES = {
|
||||||
en: {
|
en: {
|
||||||
TITLE: 'Dialog',
|
TITLE: 'Dialog',
|
||||||
BTNS: ['Cancel', 'OK'],
|
BTNS: ['Cancel', 'OK'],
|
||||||
YES_BTN: 'OK',
|
ERROR: 'The layer instance is not exists'
|
||||||
NO_BTN: 'Cancel',
|
|
||||||
ERROR: 'The layer instance is not exists',
|
|
||||||
NEED_CONTAINER: 'layer "tips" require a DOM object as container'
|
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
TITLE: '提示',
|
TITLE: '提示',
|
||||||
BTNS: ['取消', '确定'],
|
BTNS: ['取消', '确定'],
|
||||||
YES_BTN: '确定',
|
ERROR: '要关闭的layer实例不存在'
|
||||||
NO_BTN: '取消',
|
|
||||||
ERROR: '要关闭的layer实例不存在',
|
|
||||||
NEED_CONTAINER: 'tips类型需要指定一个元素节点作为容器'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LANGUAGES['zh-CN'] = LANGUAGES.zh
|
LANGUAGES['zh-CN'] = LANGUAGES.zh
|
||||||
const lang =
|
const lang =
|
||||||
LANGUAGES[window.__ENV_LANG__ || navigator.language] || LANGUAGES.en
|
LANGUAGES[window.__ENV_LANG__ || navigator.language] || LANGUAGES.en
|
||||||
|
|
||||||
let unique = null // 储存当前打开的1/2/3类型的弹窗
|
let unique = null // 储存当前打开的alert/confirm/prompt类型的弹窗
|
||||||
let lid = 0
|
|
||||||
let defconf = {
|
let defconf = {
|
||||||
type: 1, // 弹窗类型
|
type: 1, // 弹窗类型
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
|
@ -200,9 +209,6 @@ let defconf = {
|
||||||
offset: {} // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左
|
offset: {} // 弹窗出来后的坐标, 为数组,可有4个值,依次是 上右下左
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid = function() {
|
|
||||||
return 'layer-' + lid++
|
|
||||||
}
|
|
||||||
// 要保证弹层唯一的类型
|
// 要保证弹层唯一的类型
|
||||||
const UNIQUE_TYPES = ['alert', 'confirm', 'prompt']
|
const UNIQUE_TYPES = ['alert', 'confirm', 'prompt']
|
||||||
|
|
||||||
|
@ -219,57 +225,81 @@ const fixOffset = function(offset) {
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|
||||||
/* type: { // 弹窗类型对应的id值
|
|
||||||
1: 'alert',
|
|
||||||
2: 'confirm',
|
|
||||||
3: 'prompt',
|
|
||||||
4: 'iframe',
|
|
||||||
5: 'tips',
|
|
||||||
6: 'loading',
|
|
||||||
7: 'msg',
|
|
||||||
} */
|
|
||||||
|
|
||||||
function createLayer(opt) {
|
function createLayer(opt) {
|
||||||
var layDom = document.createElement('wc-layer')
|
var layDom = document.createElement('wc-layer')
|
||||||
layDom.type = opt.type
|
|
||||||
if (opt.mask) {
|
if (opt.mask) {
|
||||||
layDom.setAttribute('mask', '')
|
layDom.setAttribute('mask', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.title) {
|
layDom.title = opt.title
|
||||||
layDom.title = opt.title
|
if (opt.btns && opt.btns.length) {
|
||||||
|
layDom.props.btns = opt.btns
|
||||||
|
} else {
|
||||||
|
layDom.props.btns = lang.BTNS.concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt.intercept && typeof opt.intercept === 'function') {
|
||||||
|
layDom.props.intercept = opt.intercept
|
||||||
|
}
|
||||||
|
|
||||||
|
layDom.props.background = opt.background
|
||||||
|
layDom.props.mask = opt.mask
|
||||||
|
layDom.props.maskClose = opt.maskClose
|
||||||
|
layDom.props.maskColor = opt.maskColor
|
||||||
|
|
||||||
|
layDom.type = opt.type
|
||||||
layDom.innerHTML = opt.content
|
layDom.innerHTML = opt.content
|
||||||
document.body.appendChild(layDom)
|
document.body.appendChild(layDom)
|
||||||
|
|
||||||
return layDom
|
// 这3种类型, 只允许同时存在1个, 如果之前有弹出则关闭
|
||||||
|
if (UNIQUE_TYPES.includes(opt.type)) {
|
||||||
|
if (unique) {
|
||||||
|
unique.close()
|
||||||
|
}
|
||||||
|
unique = layDom
|
||||||
|
}
|
||||||
|
return layDom.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
const _layer = {
|
const _layer = {
|
||||||
alert(content, title) {
|
alert(content, title = lang.TITLE) {
|
||||||
return createLayer({
|
return createLayer({
|
||||||
type: 'alert',
|
type: 'alert',
|
||||||
title: title || 'Hello world!',
|
title,
|
||||||
content:
|
content,
|
||||||
content || '<p>blablablablsjkdjbskj fghjsdgfjs djfhjsdgf jhs jhj</p>',
|
|
||||||
fixed: true,
|
fixed: true,
|
||||||
mask: true
|
mask: true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
confirm(content, title) {
|
confirm(content, title = lang.TITLE, intercept) {
|
||||||
|
if (typeof title === 'function') {
|
||||||
|
intercept = title
|
||||||
|
title = lang.TITLE
|
||||||
|
}
|
||||||
return createLayer({
|
return createLayer({
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
title: title || 'Hello world!',
|
title,
|
||||||
content: content || 'blablablablsjkdjbskj fghjsdgfjs djfhjsdgf jhs jhj',
|
content,
|
||||||
fixed: true,
|
fixed: true,
|
||||||
mask: true
|
mask: true,
|
||||||
|
intercept
|
||||||
|
})
|
||||||
|
},
|
||||||
|
prompt(title = lang.TITLE, intercept) {
|
||||||
|
return createLayer({
|
||||||
|
type: 'prompt',
|
||||||
|
title,
|
||||||
|
content: `<wc-input autofocus class="layer__content__input"></wc-input>`,
|
||||||
|
fixed: true,
|
||||||
|
mask: true,
|
||||||
|
intercept
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
frame(url, extra = {}) {
|
frame(url, extra = {}) {
|
||||||
return createLayer({
|
return createLayer({
|
||||||
|
...extra,
|
||||||
type: 'frame',
|
type: 'frame',
|
||||||
content: `<iframe ref="frame" class="frame-box" src="${url}"></iframe>`,
|
content: `<iframe class="layer__content__frame" src="${url}"></iframe>`,
|
||||||
fixed: true,
|
fixed: true,
|
||||||
mask: true,
|
mask: true,
|
||||||
maskClose: true
|
maskClose: true
|
||||||
|
@ -310,25 +340,7 @@ const _layer = {
|
||||||
|
|
||||||
return _layer.open(opt)
|
return _layer.open(opt)
|
||||||
},
|
},
|
||||||
prompt(title, yescb) {
|
|
||||||
if (typeof yescb !== 'function') {
|
|
||||||
return console.error(
|
|
||||||
'argument [callback] requires a function, but ' +
|
|
||||||
typeof yescb +
|
|
||||||
' given'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let opt = {
|
|
||||||
type: 3,
|
|
||||||
prompt: '',
|
|
||||||
title,
|
|
||||||
content: `<input class="prompt-value" ref="input" :class="{alert: !prompt}" :duplex="prompt" />`,
|
|
||||||
fixed: true,
|
|
||||||
yes: yescb
|
|
||||||
}
|
|
||||||
return _layer.open(opt)
|
|
||||||
},
|
|
||||||
close: close,
|
|
||||||
open(opt) {
|
open(opt) {
|
||||||
if (typeof opt === 'string') {
|
if (typeof opt === 'string') {
|
||||||
opt = 'layerwrap-' + opt
|
opt = 'layerwrap-' + opt
|
||||||
|
@ -356,8 +368,7 @@ const _layer = {
|
||||||
} else {
|
} else {
|
||||||
return new __layer__(opt).init.$id
|
return new __layer__(opt).init.$id
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
version: Anot.ui.layer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anot.directive('layer', {
|
/* Anot.directive('layer', {
|
||||||
|
@ -494,8 +505,6 @@ const _layer = {
|
||||||
}
|
}
|
||||||
}) */
|
}) */
|
||||||
|
|
||||||
window.layer = _layer
|
|
||||||
|
|
||||||
function renderBtns(list) {
|
function renderBtns(list) {
|
||||||
var html = ''
|
var html = ''
|
||||||
list.forEach((t, i) => {
|
list.forEach((t, i) => {
|
||||||
|
@ -505,8 +514,9 @@ function renderBtns(list) {
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Layer {
|
class Layer {
|
||||||
props = {
|
props = {
|
||||||
|
btns: [],
|
||||||
type: 'msg',
|
type: 'msg',
|
||||||
title: '',
|
title: '',
|
||||||
fixed: false //是否固定位置
|
fixed: false //是否固定位置
|
||||||
|
@ -518,42 +528,56 @@ export default class Layer {
|
||||||
this.__TITLE__ = this.root.children[1].firstElementChild
|
this.__TITLE__ = this.root.children[1].firstElementChild
|
||||||
this.__BODY__ = this.root.children[1].children[1]
|
this.__BODY__ = this.root.children[1].children[1]
|
||||||
this.__CTRL__ = this.root.children[1].lastElementChild
|
this.__CTRL__ = this.root.children[1].lastElementChild
|
||||||
|
|
||||||
|
this.promise = new Promise((resolve, reject) => {
|
||||||
|
this.resolve = resolve
|
||||||
|
this.reject = reject
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
set title(val) {
|
set title(val) {
|
||||||
this.__TITLE__.textContent = val || lang.TITLE
|
if (val) {
|
||||||
|
this.__TITLE__.textContent = val
|
||||||
|
this.__TITLE__.style.display = ''
|
||||||
|
} else {
|
||||||
|
this.__TITLE__.style.display = 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set type(val) {
|
set type(val) {
|
||||||
this.props.type = val
|
var { btns } = this.props
|
||||||
|
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 'alert':
|
case 'alert':
|
||||||
this.__CTRL__.innerHTML = renderBtns(['确定'])
|
while (btns.length > 1) {
|
||||||
|
btns.splice(0, 1)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'confirm':
|
case 'confirm':
|
||||||
case 'prompt':
|
case 'prompt':
|
||||||
this.__CTRL__.innerHTML = renderBtns(['取消', '确定'])
|
while (btns.length > 2) {
|
||||||
|
btns.splice(0, 1)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'toast':
|
case 'toast':
|
||||||
break
|
|
||||||
case 'frame':
|
case 'frame':
|
||||||
|
btns = []
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
val = 'common'
|
val = 'common'
|
||||||
if (this.opt.btns) {
|
break
|
||||||
this.__CTRL__.innerHTML = renderBtns(this.opt.btns)
|
}
|
||||||
break
|
this.props.type = val
|
||||||
}
|
if (btns.length) {
|
||||||
|
this.__CTRL__.innerHTML = renderBtns(btns)
|
||||||
|
this.__CTRL__.style.display = ''
|
||||||
|
} else {
|
||||||
|
this.__CTRL__.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setAttribute('type', val)
|
this.setAttribute('type', val)
|
||||||
}
|
}
|
||||||
|
|
||||||
get fixed() {
|
|
||||||
return this.props.fixed
|
|
||||||
}
|
|
||||||
|
|
||||||
set fixed(val) {
|
set fixed(val) {
|
||||||
this.props.fixed = !!val
|
this.props.fixed = !!val
|
||||||
|
|
||||||
|
@ -575,24 +599,81 @@ export default class Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 拦截 "确定"按钮的事件
|
||||||
|
_intercept(input) {
|
||||||
|
if (this.props.intercept) {
|
||||||
|
this.props.intercept(input, _ => {
|
||||||
|
delete this.props.intercept
|
||||||
|
this.resolve(input)
|
||||||
|
this.close()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.resolve(input)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
if (this._dragIns) {
|
if (this._dragIns) {
|
||||||
this._dragIns.destroy()
|
this._dragIns.destroy()
|
||||||
}
|
}
|
||||||
|
if (UNIQUE_TYPES.includes(this.props.type)) {
|
||||||
|
unique = null
|
||||||
|
}
|
||||||
|
delete this.promise
|
||||||
|
unbind(this.__CTRL__, 'click', this._handleBtnClick)
|
||||||
this.parentNode.removeChild(this)
|
this.parentNode.removeChild(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
bind(this.__CTRL__, 'click', ev => {
|
this._handleBtnClick = bind(this.__CTRL__, 'click', ev => {
|
||||||
if (ev.target.tagName === 'BUTTON') {
|
if (ev.target.tagName === 'BUTTON') {
|
||||||
var idx = +ev.target.dataset.idx
|
var idx = +ev.target.dataset.idx
|
||||||
log(idx)
|
var { intercept, type } = this.props
|
||||||
this.close()
|
|
||||||
|
switch (type) {
|
||||||
|
case 'alert':
|
||||||
|
this.resolve()
|
||||||
|
this.close()
|
||||||
|
break
|
||||||
|
case 'confirm':
|
||||||
|
case 'prompt':
|
||||||
|
if (idx === 0) {
|
||||||
|
this.reject()
|
||||||
|
this.close()
|
||||||
|
} else {
|
||||||
|
let inputValue = type === 'prompt' ? this.__INPUT__.value : null
|
||||||
|
this._intercept(inputValue)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
// 其他类型, 如有按钮, 直接返回按钮的索引, 不作任何拦截
|
||||||
|
this.resolve(idx)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (this.props.type === 'prompt') {
|
||||||
|
this.__INPUT__ = this.__BODY__.firstElementChild.assignedNodes().pop()
|
||||||
|
this._handleSubmit = bind(this.__INPUT__, 'submit', ev => {
|
||||||
|
this._intercept(ev.detail)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.mask) {
|
||||||
|
this._handlMask = clickOutside(this.root.children[1], ev => {
|
||||||
|
if (this.props.maskClose) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unmount() {}
|
unmount() {
|
||||||
|
unbind(document, 'mousedown', this._handlMask)
|
||||||
|
}
|
||||||
|
|
||||||
watch() {
|
watch() {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
@ -606,4 +687,8 @@ export default class Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.layer = _layer
|
||||||
|
|
||||||
|
export default _layer
|
||||||
</script>
|
</script>
|
||||||
|
|
Reference in New Issue