You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.4 KiB
135 lines
4.4 KiB
|
6 years ago
|
const CLASS_HIGHLIGHTED_ELEMENT = 'guide-highlighted-element'
|
||
|
|
const CLASS_POSITION_RELATIVE = 'guide-position-relative'
|
||
|
|
const CLASS_FIX_STACKING_CONTEXT = 'guide-fix-stacking'
|
||
|
|
|
||
|
|
export function getStyleProperty(element, propertyName, prefixVendor = false) {
|
||
|
|
if (prefixVendor) {
|
||
|
|
const prefixes = ['', '-webkit-', '-ms-', 'moz-', '-o-']
|
||
|
|
for (let counter = 0; counter < prefixes.length; counter++) {
|
||
|
|
const prefixedProperty = prefixes[counter] + propertyName
|
||
|
|
const foundValue = getStyleProperty(element, prefixedProperty)
|
||
|
|
|
||
|
|
if (foundValue) {
|
||
|
|
return foundValue
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return ''
|
||
|
|
}
|
||
|
|
|
||
|
|
let propertyValue = ''
|
||
|
|
|
||
|
|
if (element.currentStyle) {
|
||
|
|
propertyValue = element.currentStyle[propertyName]
|
||
|
|
}
|
||
|
|
else if (document.defaultView && document.defaultView.getComputedStyle) {
|
||
|
|
propertyValue = document.defaultView
|
||
|
|
.getComputedStyle(element, null)
|
||
|
|
.getPropertyValue(propertyName)
|
||
|
|
}
|
||
|
|
|
||
|
|
return propertyValue && propertyValue.toLowerCase ? propertyValue.toLowerCase() : propertyValue
|
||
|
|
}
|
||
|
|
|
||
|
|
export function inAppView(element) {
|
||
|
|
let appView = document.querySelector('.app-main')
|
||
|
|
if (!appView) throw new Error('app-main未加载')
|
||
|
|
return appView.contains(element)
|
||
|
|
}
|
||
|
|
|
||
|
|
export function jump(element) {
|
||
|
|
if (!element.scrollIntoView) {
|
||
|
|
scrollManually(element)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
element.scrollIntoView({behavior: 'instant', block: 'center'})
|
||
|
|
}
|
||
|
|
catch (e) {
|
||
|
|
scrollManually(element)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function removeHighlightClasses(element) {
|
||
|
|
element.classList.remove(CLASS_HIGHLIGHTED_ELEMENT)
|
||
|
|
element.classList.remove(CLASS_POSITION_RELATIVE)
|
||
|
|
|
||
|
|
const stackFixes = document.querySelectorAll(`.${CLASS_FIX_STACKING_CONTEXT}`)
|
||
|
|
for (let counter = 0; counter < stackFixes.length; counter++) {
|
||
|
|
stackFixes[counter].classList.remove(CLASS_FIX_STACKING_CONTEXT)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function addHighlightClasses(element) {
|
||
|
|
element.classList.add(CLASS_HIGHLIGHTED_ELEMENT)
|
||
|
|
|
||
|
|
if (canMakeRelative(element)) {
|
||
|
|
element.classList.add(CLASS_POSITION_RELATIVE)
|
||
|
|
}
|
||
|
|
|
||
|
|
fixStackingContext(element)
|
||
|
|
}
|
||
|
|
|
||
|
|
export function getCalculatedPosition(element) {
|
||
|
|
const body = document.body
|
||
|
|
const documentElement = document.documentElement
|
||
|
|
|
||
|
|
const scrollTop = window.pageYOffset || documentElement.scrollTop || body.scrollTop
|
||
|
|
const scrollLeft = window.pageXOffset || documentElement.scrollLeft || body.scrollLeft
|
||
|
|
const elementRect = element.getBoundingClientRect()
|
||
|
|
|
||
|
|
return ({
|
||
|
|
top: elementRect.top + scrollTop,
|
||
|
|
left: elementRect.left + scrollLeft,
|
||
|
|
right: elementRect.left + scrollLeft + elementRect.width,
|
||
|
|
bottom: elementRect.top + scrollTop + elementRect.height,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
function canMakeRelative(element) {
|
||
|
|
const currentPosition = getStyleProperty(element, 'position')
|
||
|
|
const avoidPositionsList = ['absolute', 'fixed', 'relative']
|
||
|
|
|
||
|
|
return avoidPositionsList.indexOf(currentPosition) === -1
|
||
|
|
}
|
||
|
|
|
||
|
|
function fixStackingContext(element) {
|
||
|
|
let parentNode = element.parentNode
|
||
|
|
while (parentNode) {
|
||
|
|
if (!parentNode.tagName || parentNode.tagName.toLowerCase() === 'body') {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
const zIndex = getStyleProperty(parentNode, 'z-index')
|
||
|
|
const opacity = parseFloat(getStyleProperty(parentNode, 'opacity'))
|
||
|
|
const transform = getStyleProperty(parentNode, 'transform', true)
|
||
|
|
const transformStyle = getStyleProperty(parentNode, 'transform-style', true)
|
||
|
|
const transformBox = getStyleProperty(parentNode, 'transform-box', true)
|
||
|
|
const filter = getStyleProperty(parentNode, 'filter', true)
|
||
|
|
const perspective = getStyleProperty(parentNode, 'perspective', true)
|
||
|
|
|
||
|
|
if (
|
||
|
|
/[0-9]+/.test(zIndex)
|
||
|
|
|| opacity < 1
|
||
|
|
|| (transform && transform !== 'none')
|
||
|
|
|| (transformStyle && transformStyle !== 'flat')
|
||
|
|
|| (transformBox && transformBox !== 'border-box')
|
||
|
|
|| (filter && filter !== 'none')
|
||
|
|
|| (perspective && perspective !== 'none')
|
||
|
|
) {
|
||
|
|
parentNode.classList.add(CLASS_FIX_STACKING_CONTEXT)
|
||
|
|
}
|
||
|
|
|
||
|
|
parentNode = parentNode.parentNode
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function scrollManually(element) {
|
||
|
|
const elementRect = element.getBoundingClientRect()
|
||
|
|
const absoluteElementTop = elementRect.top + window.pageYOffset
|
||
|
|
const middle = absoluteElementTop - (window.innerHeight / 2)
|
||
|
|
|
||
|
|
window.scrollTo(0, middle)
|
||
|
|
}
|