Javascript : Tippy.js 不适用于动态内容
Javascript : Tippy.js not working for dynamic content
我有以下提示,悬停时 Ajax 调用会进行并获取数据,创建内容并将其显示。但它不适用于动态内容,因为在页面加载时
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
在页面上是静态的,但在选项卡中也是动态的。
所以下面的代码适用于静态
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
但不适用于动态。
<div id="template" style="display: none;">
Loading a new image...
</div>
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
蒂皮 jquery :
const template = document.querySelector('#template');
const initialText = template.textContent;
const tip = tippy('.otherPostTags', {
animation: 'shift-toward',
arrow: true,
html: '#template',
onShow() {
const content = this.querySelector('.tippy-content')
if (tip.loading || content.innerHTML !== initialText) return
tip.loading = true
node = document.querySelectorAll('[data-tippy]');
let id = node[0].dataset.postid;
$.ajax({
url: '/get/post/'+id+'/tags',
type: 'GET',
success: function(res){
let preparedMarkup = '';
res.tags.map(function(item) {
preparedMarkup +=
'<span class="orange-tag" style="background-color: '+item.color+'">'+
item.name +
'</span>';
});
content.innerHTML = preparedMarkup;
tip.loading = false
},
error: function(error) {
console.log(error);
content.innerHTML = 'Loading failed';
tip.loading = false
},
});
},
onHidden() {
const content = this.querySelector('.tippy-content');
content.innerHTML = initialText;
},
popperOptions: {
modifiers: {
preventOverflow: {
enabled: false
},
hide: {
enabled: false
}
}
}
});
我在这里错过了什么?
如果你想让Tippy在新元素上激活,你需要使用事件委托。 Tippy documentation 涵盖了这一点(令人沮丧的是,没有指向 link 的锚点;搜索 "event delegation")。您使用父容器元素,然后告诉 Tippy 使用什么选择器来匹配子元素。文档中的示例是:
tippy('#parent', {
target: '.child'
})
...因此对于您的示例,使用所有 .otherPostTags
元素所在的容器(在最坏的情况下为 document.body
)并使用 .otherPostTags
作为 target
:
tippy('selectorForParentElement', {
target: '.otherPostTags'
});
实例:
tippy('#container', {
target: '.otherPostTags'
});
var counter = 0;
var timer = setInterval(function() {
++counter;
var tag = document.createElement("span");
tag.title = "Tip for span #" + counter;
tag.className = "otherPostTags";
tag.innerHTML = "Span #" + counter;
document.getElementById("container").appendChild(tag);
if (counter === 6) {
clearInterval(timer);
}
}, 250);
.otherPostTags {
color: white;
background-color: #2020FF;
border: 1px solid black;
padding: 2px;
margin-left: 2px;
margin-right: 2px;
border-radius: 4px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.css" rel="stylesheet"/>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.min.js"></script>
这在 newer Tippy Version 内发生了变化。
您需要从 tippy.js
:
导入 delegate
方法
import { delegate } from 'tippy.js';
然后使用根元素上的委托方法启动你的提示工具,并通过 target
prop:
设置将具有实际工具提示的元素的选择器
delegate( '#root', {
target: '[data-tippy-content]'
} );
确保 #root
元素实际存在于您的应用程序中,或者使用其他任何元素,例如 body
。然后确保为实际元素提供 data-tippy-content
属性或相应地更改 target
选择器。
我有以下提示,悬停时 Ajax 调用会进行并获取数据,创建内容并将其显示。但它不适用于动态内容,因为在页面加载时
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
在页面上是静态的,但在选项卡中也是动态的。
所以下面的代码适用于静态
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
但不适用于动态。
<div id="template" style="display: none;">
Loading a new image...
</div>
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
蒂皮 jquery :
const template = document.querySelector('#template');
const initialText = template.textContent;
const tip = tippy('.otherPostTags', {
animation: 'shift-toward',
arrow: true,
html: '#template',
onShow() {
const content = this.querySelector('.tippy-content')
if (tip.loading || content.innerHTML !== initialText) return
tip.loading = true
node = document.querySelectorAll('[data-tippy]');
let id = node[0].dataset.postid;
$.ajax({
url: '/get/post/'+id+'/tags',
type: 'GET',
success: function(res){
let preparedMarkup = '';
res.tags.map(function(item) {
preparedMarkup +=
'<span class="orange-tag" style="background-color: '+item.color+'">'+
item.name +
'</span>';
});
content.innerHTML = preparedMarkup;
tip.loading = false
},
error: function(error) {
console.log(error);
content.innerHTML = 'Loading failed';
tip.loading = false
},
});
},
onHidden() {
const content = this.querySelector('.tippy-content');
content.innerHTML = initialText;
},
popperOptions: {
modifiers: {
preventOverflow: {
enabled: false
},
hide: {
enabled: false
}
}
}
});
我在这里错过了什么?
如果你想让Tippy在新元素上激活,你需要使用事件委托。 Tippy documentation 涵盖了这一点(令人沮丧的是,没有指向 link 的锚点;搜索 "event delegation")。您使用父容器元素,然后告诉 Tippy 使用什么选择器来匹配子元素。文档中的示例是:
tippy('#parent', {
target: '.child'
})
...因此对于您的示例,使用所有 .otherPostTags
元素所在的容器(在最坏的情况下为 document.body
)并使用 .otherPostTags
作为 target
:
tippy('selectorForParentElement', {
target: '.otherPostTags'
});
实例:
tippy('#container', {
target: '.otherPostTags'
});
var counter = 0;
var timer = setInterval(function() {
++counter;
var tag = document.createElement("span");
tag.title = "Tip for span #" + counter;
tag.className = "otherPostTags";
tag.innerHTML = "Span #" + counter;
document.getElementById("container").appendChild(tag);
if (counter === 6) {
clearInterval(timer);
}
}, 250);
.otherPostTags {
color: white;
background-color: #2020FF;
border: 1px solid black;
padding: 2px;
margin-left: 2px;
margin-right: 2px;
border-radius: 4px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.css" rel="stylesheet"/>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.min.js"></script>
这在 newer Tippy Version 内发生了变化。
您需要从 tippy.js
:
delegate
方法
import { delegate } from 'tippy.js';
然后使用根元素上的委托方法启动你的提示工具,并通过 target
prop:
delegate( '#root', {
target: '[data-tippy-content]'
} );
确保 #root
元素实际存在于您的应用程序中,或者使用其他任何元素,例如 body
。然后确保为实际元素提供 data-tippy-content
属性或相应地更改 target
选择器。