This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

layer重构完成

old
宇天 2019-09-04 18:12:41 +08:00
parent 823e17e5ba
commit 33111851db
3 changed files with 116 additions and 267 deletions

View File

@ -1,30 +0,0 @@
v1.0.0-base / 2017-09-20
==================
+ 统一字体图标
+ 精简动画类型
+ 优化样式
v0.0.4-base / 2017-04-20
==================
+ 优化offset的处理
+ 优化样式
v0.0.3-base / 2017-04-15
==================
+ 重构wrap方式创建弹窗实例的实现
v0.0.2-base / 2017-04-13
==================
+ 修复:layer方式创建实例时,漏掉自身的bug;
+ 修复layer.open()方法打开已有实例时不返回id的bug;
+ 修复layer.close()方法关闭实例时,未修改实例状态的bug;
+ 修改特殊模式下的实例的最小宽度为10px;
+ 优化:layer方式创建实例的逻辑处理;
+ 优化layer.alert()方法参数的处理;
v0.0.1-base / 2017-04-06
==================
+ 完成layer base版移植

View File

@ -1,147 +0,0 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2016-09-21 01:36:29
*
*/
'use strict'
import layer from './core'
const log = console.log
/* Anot.directive('layer', {
priority: 8090,
init: function(binding) {
// 去掉:layer属性,避免二次扫描
binding.element.removeAttribute(binding.name)
if (!binding.param || binding.param !== 'tips') {
binding.param = '' // 去掉param,保证之后的逻辑处理正常
binding.element.style.display = 'none'
}
},
update: function(val) {
if (!val) {
return console.error(
`SyntaxError: Unexpected [${this.name}=${this.expr}]`
)
}
let state = Object.assign({ type: 7, wrap: true }, this.element.dataset)
if (!this.param) {
let init = { $id: 'layerwrap-' + val, state, props: {} }
if (state.hasOwnProperty('area')) {
state.area = state.area.split(',')
}
if (state.hasOwnProperty('shift')) {
state.shift = fixOffset(new Function(`return ${state.shift}`)())
}
if (state.hasOwnProperty('offset')) {
state.offset = fixOffset(new Function(`return ${state.offset}`)())
}
if (state.hasOwnProperty('btns')) {
state.btns = state.btns.split(',')
}
if (!state.hasOwnProperty('menubar')) {
state.menubar = false
}
let tmp = new __layer__().__init__(init)
//去掉data-*属性
for (let i in this.element.dataset) {
delete this.element.dataset[i]
}
layerObj[tmp.init.$id] = {
obj: tmp,
parentElem: this.element.parentNode,
wrap: this.element,
show: false
}
layerDom[tmp.init.$id] = tmp.create()
} else if (this.param === 'tips') {
let tips = document.createElement('div')
let cont = document.createElement('span')
let arrow = document.createElement('i')
let $container = Anot(this.element)
let { position } = getComputedStyle(this.element)
tips.className = 'do-layer__tips'
cont.className = 'layer-content'
arrow.className = 'arrow'
cont.textContent = val
tips.appendChild(cont)
tips.appendChild(arrow)
if (position === 'static') {
this.element.style.position = 'relative'
}
this.element.appendChild(tips)
let style = {}
if (state.color) {
style.color = state.color
}
if (state.color) {
style.background = state.background
}
let cw = $container.innerWidth()
let ch = $container.innerHeight()
let arrowOffset = ['top']
// log(tips, layw, layh)
Anot(tips).css(style)
$container.bind('mouseenter', ev => {
let tmpStyle = { visibility: 'visible' }
let layw = tips.clientWidth
let layh = tips.clientHeight
let { left, top } = $container.offset()
let ol = left - $doc.scrollLeft()
let ot = top - $doc.scrollTop()
// 判断位置是以确定出现 在上还是在下
if (ot < layh + 8) {
arrowOffset[0] = 'bottom'
arrow.style.borderBottomColor = state.background
tmpStyle.bottom = ''
tmpStyle.top = ch + 8
} else {
arrow.style.borderTopColor = state.background
tmpStyle.top = ''
tmpStyle.bottom = ch + 8
}
if (ol + cw * 0.7 + layw > window.innerWidth) {
tmpStyle.left = cw * 0.3 - layw
arrowOffset[1] = 'left'
} else {
tmpStyle.left = cw * 0.7
}
arrow.classList.add('offset-' + arrowOffset.join('-'))
Anot(tips).css(tmpStyle)
})
$container.bind('mouseleave', () => {
setTimeout(() => {
arrow.classList.remove('offset-' + arrowOffset.join('-'))
arrowOffset = ['top']
arrow.style.borderBottomColor = ''
arrow.style.borderTopColor = ''
tips.style.visibility = 'hidden'
}, 100)
})
}
}
}) */
export default layer

View File

@ -7,12 +7,22 @@
</template>
<style lang="scss">
:host {
display: flex;
display: none;
justify-content: center;
align-items: center;
width: auto;
height: auto;
}
:host([alert]),
:host([confirm]),
:host([prompt]),
:host([frame]),
:host([toast]),
:host([notify]),
:host([common]) {
display: flex;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
@ -187,9 +197,9 @@
backdrop-filter: blur(5px);
}
:host([type='alert']),
:host([type='confirm']),
:host([type='prompt']) {
:host([alert]),
:host([confirm]),
:host([prompt]) {
.layer {
max-width: 600px;
min-width: 300px;
@ -200,7 +210,7 @@
}
}
}
:host([type='notify']) {
:host([notify]) {
.layer {
width: 300px;
height: 120px;
@ -210,7 +220,7 @@
}
}
}
:host([type='toast']) {
:host([toast]) {
.layer {
box-shadow: none;
@ -230,13 +240,11 @@ import { nextTick, bind, unbind, clickOutside } from '../utils'
const LANGUAGES = {
en: {
TITLE: 'Dialog',
BTNS: ['Cancel', 'OK'],
ERROR: 'The layer instance is not exists'
BTNS: ['Cancel', 'OK']
},
zh: {
TITLE: '提示',
BTNS: ['取消', '确定'],
ERROR: '要关闭的layer实例不存在'
BTNS: ['取消', '确定']
}
}
LANGUAGES['zh-CN'] = LANGUAGES.zh
@ -260,9 +268,20 @@ function renderBtns(list) {
class Layer {
props = {
left: 'auto',
right: 'auto',
top: 'auto',
bottom: 'auto',
from: Object.create(null),
to: Object.create(null),
btns: [],
type: '',
title: '',
blur: false,
background: null,
mask: false,
'mask-close': false,
'mask-color': null,
fixed: false //是否固定位置
}
@ -282,7 +301,14 @@ class Layer {
set title(val) {
this.props.title = val
if (val) {
this.__TITLE__.textContent = val
if (this.__TITLE__.firstElementChild) {
this.__TITLE__.insertBefore(
document.createTextNode(val),
this.__TITLE__.firstElementChild
)
} else {
this.__TITLE__.textContent = val
}
this.__TITLE__.style.display = ''
} else {
this.__TITLE__.style.display = 'none'
@ -292,7 +318,7 @@ class Layer {
set type(val) {
var { btns } = this.props
if (this._handleBtnClick) {
if (!val || this._handleBtnClick) {
return
}
@ -330,7 +356,7 @@ class Layer {
this.__CTRL__.style.display = 'none'
}
this.setAttribute('type', val)
this.setAttribute(val, '')
}
set fixed(val) {
@ -375,32 +401,46 @@ class Layer {
}
close(force) {
if (this._dragIns) {
this._dragIns.destroy()
}
if (UNIQUE_TYPES.includes(this.props.type)) {
uniqueInstance = null
}
delete this.promise
unbind(this.__CTRL__, 'click', this._handleBtnClick)
// 离场动画
if (this.props.from && !force) {
let _style = 'opacity:0;'
for (let k in this.props.from) {
_style += `${k}:${this.props.from[k]};`
if (this.wrapped === false) {
if (this._dragIns) {
this._dragIns.destroy()
}
this.root.children[1].style.cssText += _style
this.timer = setTimeout(() => {
if (UNIQUE_TYPES.includes(this.props.type)) {
uniqueInstance = null
}
delete this.promise
unbind(this.__CTRL__, 'click', this._handleBtnClick)
// 离场动画
if (this.props.from && !force) {
let _style = 'opacity:0;'
for (let k in this.props.from) {
_style += `${k}:${this.props.from[k]};`
}
this.root.children[1].style.cssText += _style
this.timer = setTimeout(() => {
this.parentNode.removeChild(this)
}, 200)
} else {
clearTimeout(this.timer)
this.parentNode.removeChild(this)
}, 200)
}
} else {
clearTimeout(this.timer)
this.parentNode.removeChild(this)
this.removeAttribute('common')
}
}
show() {
if (this.wrapped === false) {
return
}
this.setAttribute('common', '')
}
mounted() {
this.type = this.props.type
this.title = this.props.title
this._handleBtnClick = bind(this.__CTRL__, 'click', ev => {
if (ev.target.tagName === 'BUTTON') {
var idx = +ev.target.dataset.idx
@ -437,6 +477,10 @@ class Layer {
})
}
if (this.props.mask) {
this.setAttribute('mask', '')
}
this._updateFixedStat()
/* ------------------------ */
@ -444,8 +488,10 @@ class Layer {
/* ------------------------ */
if (this.props.mask) {
this._handlMask = clickOutside(this.root.children[1], ev => {
if (this.props.maskClose) {
this.reject(null)
if (this.props['mask-close']) {
if (this.wrapped === false) {
this.reject(null)
}
this.close()
} else {
if (UNIQUE_TYPES.includes(this.props.type)) {
@ -457,8 +503,8 @@ class Layer {
}
})
if (this.props.maskColor) {
this.style.backgroundColor = this.props.maskColor
if (this.props['mask-color']) {
this.style.backgroundColor = this.props['mask-color']
}
}
@ -524,8 +570,25 @@ class Layer {
switch (name) {
case 'title':
case 'type':
if (val !== this.props[name]) {
this[name] = val
this[name] = val
break
case 'mask-color':
case 'background':
this.props[name] = val
break
case 'mask':
case 'mask-close':
case 'blur':
this.props[name] = true
break
case 'left':
case 'right':
case 'top':
case 'bottom':
if (val !== null) {
this.props.from[name] = val
this.props.to = this.props.from
this.removeAttribute(name)
}
break
case 'fixed':
@ -535,7 +598,7 @@ class Layer {
}
}
function createLayer(opt) {
function _layer(opt) {
var layDom = document.createElement('wc-layer')
if (opt.type === 'toast') {
@ -554,9 +617,7 @@ function createLayer(opt) {
}
toastInstance = layDom
} else {
if (opt.mask) {
layDom.setAttribute('mask', '')
}
layDom.props.mask = opt.mask
if (opt.btns === false) {
layDom.props.btns = []
@ -571,14 +632,14 @@ function createLayer(opt) {
}
layDom.props.mask = opt.mask
layDom.props.maskClose = opt.maskClose
layDom.props['mask-close'] = opt['mask-close']
if (opt.hasOwnProperty('overflow')) {
layDom.props.overflow = opt.overflow
}
/* 额外样式 */
layDom.props.maskColor = opt.maskColor
layDom.props['mask-color'] = opt['mask-color']
layDom.props.blur = opt.blur
@ -607,55 +668,20 @@ function createLayer(opt) {
}
}
layDom.title = opt.title
layDom.type = opt.type
layDom.fixed = opt.fixed
layDom.props.type = opt.type
layDom.props.fixed = opt.fixed
layDom.props.title = opt.title
layDom.innerHTML = opt.content
layDom.wrapped = false // 用于区分是API创建的还是包裹现有的节点
document.body.appendChild(layDom)
return layDom.promise
}
const _layer = function(opt) {
if (typeof opt === 'string') {
opt = 'layerwrap-' + opt
if (!layerObj[opt]) {
throw new Error(lang.ERROR)
} else {
//只能显示一个实例
if (layerObj[opt].show) {
return opt
}
layerObj[opt].show = true
layerObj[opt].parentElem.appendChild(layerDom[opt][0])
layerDom[opt][0]
.querySelector('.layer-content')
.appendChild(layerObj[opt].wrap)
layerObj[opt].wrap.style.display = ''
if (!Anot.vmodels[opt]) {
Anot(layerObj[opt].obj.init)
}
layerObj[opt].obj.show()
return opt
}
} else {
return createLayer(opt)
}
}
Object.defineProperty(_layer, '__map__', {
value: {},
writable: true,
enumerable: false,
configurable: true
})
Object.assign(_layer, {
alert(content, title = lang.TITLE) {
return createLayer({
return this({
type: 'alert',
title,
content,
@ -668,7 +694,7 @@ Object.assign(_layer, {
intercept = title
title = lang.TITLE
}
return createLayer({
return this({
type: 'confirm',
title,
content,
@ -678,7 +704,7 @@ Object.assign(_layer, {
})
},
prompt(title = lang.TITLE, intercept) {
return createLayer({
return this({
type: 'prompt',
title,
content: `<wc-input autofocus class="layer__content__input"></wc-input>`,
@ -688,17 +714,17 @@ Object.assign(_layer, {
})
},
frame(url, extra = {}) {
return createLayer({
return this({
...extra,
type: 'frame',
content: `<iframe class="layer__content__frame" src="${url}"></iframe>`,
fixed: true,
mask: true,
maskClose: true
'mask-close': true
})
},
notify(content) {
return createLayer({
return this({
type: 'notify',
title: '通知',
content,
@ -718,7 +744,7 @@ Object.assign(_layer, {
type = 'info'
}
return createLayer({
return this({
content: `
<div class="layer__content__toast style-${type}">
<wc-icon size="mini" is="${type}"></wc-icon>