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.
224 lines
6.4 KiB
224 lines
6.4 KiB
'use strict'
|
|
|
|
// 等待初始化完毕
|
|
document.addEventListener('UniAppJSBridgeReady', () => {
|
|
document.body.onclick = function () {
|
|
return uni.postMessage({
|
|
data: {
|
|
action: 'onClick'
|
|
}
|
|
})
|
|
}
|
|
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onJSBridgeReady'
|
|
}
|
|
})
|
|
})
|
|
let options
|
|
let medias = []
|
|
/**
|
|
* @description 获取标签的所有属性
|
|
* @param {Element} ele
|
|
*/
|
|
|
|
function getAttrs(ele) {
|
|
const attrs = Object.create(null)
|
|
|
|
for (let i = ele.attributes.length; i--;) {
|
|
attrs[ele.attributes[i].name] = ele.attributes[i].value
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
/**
|
|
* @description 图片加载出错
|
|
*/
|
|
|
|
function onImgError() {
|
|
if (options[1]) {
|
|
this.src = options[1]
|
|
this.onerror = null
|
|
} // 取消监听点击
|
|
|
|
this.onclick = null
|
|
this.ontouchstart = null
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onError',
|
|
source: 'img',
|
|
attrs: getAttrs(this)
|
|
}
|
|
})
|
|
}
|
|
/**
|
|
* @description 创建 dom 结构
|
|
* @param {object[]} nodes 节点数组
|
|
* @param {Element} parent 父节点
|
|
* @param {string} namespace 命名空间
|
|
*/
|
|
|
|
function createDom(nodes, parent, namespace) {
|
|
const _loop = function _loop(i) {
|
|
const node = nodes[i]
|
|
let ele = void 0
|
|
|
|
if (!node.type || node.type == 'node') {
|
|
let { name } = node // svg 需要设置 namespace
|
|
|
|
if (name == 'svg') namespace = 'http://www.w3.org/2000/svg'
|
|
if (name == 'html' || name == 'body') name = 'div' // 创建标签
|
|
|
|
if (!namespace) ele = document.createElement(name); else ele = document.createElementNS(namespace, name) // 设置属性
|
|
|
|
for (const item in node.attrs) {
|
|
ele.setAttribute(item, node.attrs[item])
|
|
} // 递归创建子节点
|
|
|
|
if (node.children) createDom(node.children, ele, namespace) // 处理图片
|
|
|
|
if (name == 'img') {
|
|
if (!ele.src && ele.getAttribute('data-src')) ele.src = ele.getAttribute('data-src')
|
|
|
|
if (!node.attrs.ignore) {
|
|
// 监听图片点击事件
|
|
ele.onclick = function (e) {
|
|
e.stopPropagation()
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onImgTap',
|
|
attrs: getAttrs(this)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
if (options[2]) {
|
|
image = new Image()
|
|
image.src = ele.src
|
|
ele.src = options[2]
|
|
|
|
image.onload = function () {
|
|
ele.src = this.src
|
|
}
|
|
|
|
image.onerror = function () {
|
|
ele.onerror()
|
|
}
|
|
}
|
|
|
|
ele.onerror = onImgError
|
|
} // 处理链接
|
|
else if (name == 'a') {
|
|
ele.addEventListener('click', function (e) {
|
|
e.stopPropagation()
|
|
e.preventDefault() // 阻止默认跳转
|
|
|
|
const href = this.getAttribute('href')
|
|
let offset
|
|
if (href && href[0] == '#') offset = (document.getElementById(href.substr(1)) || {}).offsetTop
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onLinkTap',
|
|
attrs: getAttrs(this),
|
|
offset
|
|
}
|
|
})
|
|
}, true)
|
|
} // 处理音视频
|
|
else if (name == 'video' || name == 'audio') {
|
|
medias.push(ele)
|
|
|
|
if (!node.attrs.autoplay) {
|
|
if (!node.attrs.controls) ele.setAttribute('controls', 'true') // 空白图占位
|
|
|
|
if (!node.attrs.poster) ele.setAttribute('poster', "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'/>")
|
|
}
|
|
|
|
if (options[3]) {
|
|
ele.onplay = function () {
|
|
for (let _i = 0; _i < medias.length; _i++) {
|
|
if (medias[_i] != this) medias[_i].pause()
|
|
}
|
|
}
|
|
}
|
|
|
|
ele.onerror = function () {
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onError',
|
|
source: name,
|
|
attrs: getAttrs(this)
|
|
}
|
|
})
|
|
}
|
|
} // 处理表格
|
|
else if (name == 'table' && options[4] && !ele.style.cssText.includes('inline')) {
|
|
const div = document.createElement('div')
|
|
div.style.overflow = 'auto'
|
|
div.appendChild(ele)
|
|
ele = div
|
|
} else if (name == 'svg') namespace = void 0
|
|
} else ele = document.createTextNode(node.text.replace(/&/g, '&'))
|
|
|
|
parent.appendChild(ele)
|
|
}
|
|
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
var image
|
|
|
|
_loop(i)
|
|
}
|
|
} // 设置 html 内容
|
|
|
|
window.setContent = function (nodes, opts, append) {
|
|
const ele = document.getElementById('content') // 背景颜色
|
|
|
|
if (opts[0]) document.body.bgColor = opts[0] // 长按复制
|
|
|
|
if (!opts[5]) ele.style.userSelect = 'none'
|
|
|
|
if (!append) {
|
|
ele.innerHTML = '' // 不追加则先清空
|
|
|
|
medias = []
|
|
}
|
|
|
|
options = opts
|
|
const fragment = document.createDocumentFragment()
|
|
createDom(nodes, fragment)
|
|
ele.appendChild(fragment) // 触发事件
|
|
|
|
let height = ele.scrollHeight
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onLoad',
|
|
height
|
|
}
|
|
})
|
|
clearInterval(window.timer)
|
|
let ready = false
|
|
window.timer = setInterval(() => {
|
|
if (ele.scrollHeight != height) {
|
|
height = ele.scrollHeight
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onHeightChange',
|
|
height
|
|
}
|
|
})
|
|
} else if (!ready) {
|
|
ready = true
|
|
uni.postMessage({
|
|
data: {
|
|
action: 'onReady'
|
|
}
|
|
})
|
|
}
|
|
}, 350)
|
|
} // 回收计时器
|
|
|
|
window.onunload = function () {
|
|
clearInterval(window.timer)
|
|
}
|
|
|