118 lines
3.8 KiB
Vue
118 lines
3.8 KiB
Vue
<template>
|
|
<div class="w-full h-full">
|
|
<div class="h-full max-h-full w-full">
|
|
<div class="ebook-viewer absolute overflow-y-scroll left-0 right-0 top-12 w-full max-w-4xl m-auto z-10 border border-black border-opacity-20 shadow-md bg-white">
|
|
<iframe title="html-viewer" width="100%"> Loading </iframe>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import MobiParser from '@/assets/ebooks/mobi.js'
|
|
import HtmlParser from '@/assets/ebooks/htmlParser.js'
|
|
import defaultCss from '@/assets/ebooks/basic.js'
|
|
|
|
export default {
|
|
props: {
|
|
url: String
|
|
},
|
|
data() {
|
|
return {}
|
|
},
|
|
computed: {},
|
|
methods: {
|
|
addHtmlCss() {
|
|
let iframe = document.getElementsByTagName('iframe')[0]
|
|
if (!iframe) return
|
|
let doc = iframe.contentDocument
|
|
if (!doc) return
|
|
let style = doc.createElement('style')
|
|
style.id = 'default-style'
|
|
style.textContent = defaultCss
|
|
doc.head.appendChild(style)
|
|
},
|
|
handleIFrameHeight(iFrame) {
|
|
const isElement = (obj) => !!(obj && obj.nodeType === 1)
|
|
|
|
var body = iFrame.contentWindow.document.body,
|
|
html = iFrame.contentWindow.document.documentElement
|
|
iFrame.height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight) * 2
|
|
|
|
setTimeout(() => {
|
|
let lastchild = body.lastElementChild
|
|
let lastEle = body.lastChild
|
|
|
|
let itemAs = body.querySelectorAll('a')
|
|
let itemPs = body.querySelectorAll('p')
|
|
let lastItemA = itemAs[itemAs.length - 1]
|
|
let lastItemP = itemPs[itemPs.length - 1]
|
|
let lastItem
|
|
if (isElement(lastItemA) && isElement(lastItemP)) {
|
|
if (lastItemA.clientHeight + lastItemA.offsetTop > lastItemP.clientHeight + lastItemP.offsetTop) {
|
|
lastItem = lastItemA
|
|
} else {
|
|
lastItem = lastItemP
|
|
}
|
|
}
|
|
|
|
if (!lastchild && !lastItem && !lastEle) return
|
|
if (lastEle.nodeType === 3 && !lastchild && !lastItem) return
|
|
|
|
let nodeHeight = 0
|
|
if (lastEle.nodeType === 3 && document.createRange) {
|
|
let range = document.createRange()
|
|
range.selectNodeContents(lastEle)
|
|
if (range.getBoundingClientRect) {
|
|
let rect = range.getBoundingClientRect()
|
|
if (rect) {
|
|
nodeHeight = rect.bottom - rect.top
|
|
}
|
|
}
|
|
}
|
|
var lastChildHeight = isElement(lastchild) ? lastchild.clientHeight + lastchild.offsetTop : 0
|
|
var lastEleHeight = isElement(lastEle) ? lastEle.clientHeight + lastEle.offsetTop : 0
|
|
var lastItemHeight = isElement(lastItem) ? lastItem.clientHeight + lastItem.offsetTop : 0
|
|
iFrame.height = Math.max(lastChildHeight, lastEleHeight, lastItemHeight) + 100 + nodeHeight
|
|
}, 500)
|
|
},
|
|
async initMobi() {
|
|
// Fetch mobi file as blob
|
|
var buff = await this.$axios.$get(this.url, {
|
|
responseType: 'blob'
|
|
})
|
|
var reader = new FileReader()
|
|
reader.onload = async (event) => {
|
|
var file_content = event.target.result
|
|
|
|
let mobiFile = new MobiParser(file_content)
|
|
|
|
let content = await mobiFile.render()
|
|
let htmlParser = new HtmlParser(new DOMParser().parseFromString(content.outerHTML, 'text/html'))
|
|
var anchoredDoc = htmlParser.getAnchoredDoc()
|
|
|
|
let iFrame = document.getElementsByTagName('iframe')[0]
|
|
iFrame.contentDocument.body.innerHTML = anchoredDoc.documentElement.outerHTML
|
|
|
|
// Add css
|
|
let style = iFrame.contentDocument.createElement('style')
|
|
style.id = 'default-style'
|
|
style.textContent = defaultCss
|
|
iFrame.contentDocument.head.appendChild(style)
|
|
|
|
this.handleIFrameHeight(iFrame)
|
|
}
|
|
reader.readAsArrayBuffer(buff)
|
|
}
|
|
},
|
|
mounted() {
|
|
this.initMobi()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.ebook-viewer {
|
|
height: calc(100% - 96px);
|
|
}
|
|
</style> |