hubspot 代码将 2 个 js 文件插入到 中,<head>
并将一些内联样式表注入到其中<body>
- 其中一个 js 文件 (conversations-embed.js) 创建了一个带有 id 的 div #hubspot-messages-iframe-container
。顾名思义,它包含一个带有聊天窗口的 iframe。它还为body添加了一堆css。
这里的主要问题是 Turbolinks 会替换<body>
每页更改中的所有内容,从而使 hubspot 脚本不知道页面已更改的事实。由于一切都被替换了,脚本注入的div和css就消失了。
我的第一次尝试是将聊天容器 div 克隆到一个窗口变量中,并用于事件appendChild(clonedNode)
中的event.data.newBody
元素turbolinks:before-render
。虽然这有点工作,但它不是很优雅。每次更改页面时,它都会消失并重新出现。此外,状态没有被延续,所以如果我关闭窗口,它将在下一页打开,依此类推。
起作用的是将#hubspot-messages-iframe-container
正文中的内容移到 html 标记本身中,使其免受 turbolinks 的危害。它的状态保持不变(打开、关闭等),不会闪烁或有任何副作用。请记住,您必须手动将其从您可能不想要的页面中删除。
我知道这有点 hacky,但它可以工作,直到他们有某种 api 来重新初始化聊天窗口,这是一种解决方法:
document.addEventListener("turbolinks:load", function() {
let targetNode = document.body
let config = { childList: true }
let callback = function() {
if (document.body.querySelector('#hubspot-messages-iframe-container')) {
document.documentElement.appendChild(
document.getElementById('hubspot-messages-iframe-container')
)
observer.disconnect()
}
}
let observer = new MutationObserver(callback)
if (!document.querySelector("html > #hubspot-messages-iframe-container")) {
observer.observe(targetNode, config)
}
})
您还需要复制注入主体的样式,因为 Turbolinks 也会替换它。这就是我最终得到的(转换为 Sass):
html.hs-messages-widget-open.hs-messages-mobile
height: 100% !important
overflow: hidden !important
position: relative !important
body
height: 100% !important
overflow: hidden !important
position: relative !important
margin: 0 !important
#hubspot-messages-iframe-container
display: initial !important
z-index: 2147483647
position: fixed !important
bottom: 0 !important
right: 0 !important
&.internal
z-index: 1016
iframe
min-width: 108px
.shadow
display: initial !important
z-index: -1
position: absolute
width: 0
height: 0
bottom: 0
right: 0
content: ""
&.internal
display: none !important
&.active
width: 400px
height: 400px
background: radial-gradient(ellipse at bottom right, rgba(29, 39, 54, 0.16) 0, rgba(29, 39, 54, 0) 72%)
iframe
display: initial !important
width: 100% !important
height: 100% !important
border: none !important
position: absolute !important
bottom: 0 !important
right: 0 !important
background: transparent !important