saven
Version:
217 lines (190 loc) • 8.44 kB
JavaScript
import { inlineStyle } from '../utils'
export default class Toast {
constructor () {
const noop = function () {}
this.options = {
title: '',
icon: 'none',
image: '',
duration: 1500,
mask: false,
success: noop,
fail: noop,
complete: noop
}
}
getstyle (name) {
return {
maskStyle: {
'position': 'fixed',
'z-index': '1000',
'top': '0',
'right': '0',
'left': '0',
'bottom': '0'
},
toastStyle: {
'z-index': '5000',
'box-sizing': 'border-box',
'display': 'flex',
'flex-direction': 'column',
'justify-content': 'center',
'-webkit-justify-content': 'center',
'position': 'fixed',
'top': '50%',
'left': '50%',
'min-width': '120px',
'max-width': '200px',
'min-height': '120px',
'padding': '15px',
'transform': 'translate(-50%, -50%)',
'border-radius': '5px',
'text-align': 'center',
'line-height': '1.6',
'color': '#FFFFFF',
'background': 'rgba(17, 17, 17, 0.7)'
},
successStyle: {
'margin': '0',
'vertical-align': 'middle',
'font-family': 'taro',
'-webkit-font-smoothing': 'antialiased',
'color': '#FFFFFF',
'font-size': '55px',
'line-height': '1'
},
loadingStyle: {
'margin': '6px auto',
'width': '38px',
'height': '38px',
'-webkit-animation': 'taroLoading 1s steps(12, end) infinite',
'animation': 'taroLoading 1s steps(12, end) infinite',
'background': 'transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat',
'background-size': '100%'
},
imageStyle: {
'margin': '6px auto',
'width': '40px',
'height': '40px',
'background': 'transparent no-repeat',
'background-size': '100%'
},
textStyle: {
'margin': '0',
'font-size': '16px'
}
}
}
create (options = {}) {
// style
const { maskStyle, toastStyle, successStyle, loadingStyle, imageStyle, textStyle } = this.getstyle()
// configuration
Object.assign(this.options, options)
const config = this.options
// wrapper
this.el = document.createElement('div')
this.el.className = 'taro__toast'
this.el.style.opacity = '0'
this.el.style.transition = 'opacity 0.1s linear'
// mask
this.mask = document.createElement('div')
this.mask.setAttribute('style', inlineStyle(maskStyle))
this.mask.style.display = config.mask ? 'block' : 'none'
// icon
this.icon = document.createElement('p')
if (config.image) {
this.icon.setAttribute('style', inlineStyle(Object.assign({}, imageStyle, {
'background-image': `url(${config.image})`
})))
} else {
const iconStyle = config.icon === 'loading' ? loadingStyle : successStyle
if (config.icon === 'none') Object.assign(iconStyle, { 'display': 'none' })
this.icon.setAttribute('style', inlineStyle(iconStyle))
if (config.icon !== 'loading') this.icon.textContent = ''
}
// toast
this.toast = document.createElement('div')
if (config.icon === 'none') {
Object.assign(toastStyle, {
'min-height': '0',
'padding': '10px 15px'
})
}
this.toast.setAttribute('style', inlineStyle(toastStyle))
// title
this.title = document.createElement('p')
this.title.setAttribute('style', inlineStyle(textStyle))
this.title.textContent = config.title
// result
this.toast.appendChild(this.icon)
this.toast.appendChild(this.title)
this.el.appendChild(this.mask)
this.el.appendChild(this.toast)
// show immediately
document.body.appendChild(this.el)
setTimeout(() => { this.el.style.opacity = '1' }, 0)
this.type = config._type
// disappear after duration
config.duration >= 0 && this.hide(config.duration, this.type)
const errMsg = this.type === 'loading' ? 'showLoading:ok' : 'showToast:ok'
config.success && config.success({ errMsg })
config.complete && config.complete({ errMsg })
return Promise.resolve({ errMsg })
}
show (options = {}) {
const config = this.options
// title
if (config.title !== options.title) this.title.textContent = options.title
// mask
if (config.mask !== options.mask) this.mask.style.display = options.mask ? 'block' : 'none'
// image
const { toastStyle, successStyle, loadingStyle, imageStyle } = this.getstyle()
if (config.image !== options.image) {
if (options.image) {
this.icon.setAttribute('style', inlineStyle(Object.assign({}, imageStyle, {
'background-image': `url(${options.image})`
})))
this.icon.textContent = ''
} else {
const iconStyle = options.icon === 'loading' ? loadingStyle : successStyle
if (options.icon === 'none') Object.assign(iconStyle, { 'display': 'none' })
this.icon.setAttribute('style', inlineStyle(iconStyle))
this.icon.textContent = options.icon === 'loading' ? '' : ''
}
} else {
if (!options.image && config.icon !== options.icon) {
const iconStyle = options.icon === 'loading' ? loadingStyle : successStyle
if (options.icon === 'none') Object.assign(iconStyle, { 'display': 'none' })
this.icon.setAttribute('style', inlineStyle(iconStyle))
this.icon.textContent = options.icon === 'loading' ? '' : ''
}
}
// toast
if (options.icon === 'none') {
Object.assign(toastStyle, {
'min-height': '0',
'padding': '10px 15px'
})
}
this.toast.setAttribute('style', inlineStyle(toastStyle))
Object.assign(config, options)
// show
this.el.style.display = 'block'
setTimeout(() => { this.el.style.opacity = '1' }, 0)
this.type = config._type
// disappear after duration
config.duration >= 0 && this.hide(config.duration, this.type)
const errMsg = this.type === 'loading' ? 'showLoading:ok' : 'showToast:ok'
config.success && config.success({ errMsg })
config.complete && config.complete({ errMsg })
return Promise.resolve({ errMsg })
}
hide (duration = 0, type) {
if (this.type !== type) return
if (this.hideTimer) clearTimeout(this.hideTimer)
this.hideTimer = setTimeout(() => {
this.el.style.opacity = '0'
setTimeout(() => { this.el.style.display = 'none' }, 100)
}, duration)
}
}