Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript : Destroy tippy.js instance

I have the following code which shows a tooltip containing dynamic data. Its working fine, But it shows same tooltip for all.

I have used tip._tippy.destroy(); bit didn't worked.

<div id="template" style="display: none;">
    Loading a tooltip...
</div>

Element on which tooltip shows above:

<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>

Js:

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
            },
        });
    },
    onHidden() {
        const content = this.querySelector('.tippy-content');
        content.innerHTML = initialText;
    },
});

When i hover over, The tooptip shows with tags coming from the database, But it shows same tags/data on hover, The data comes different but it shows tooltip which comes on first hover.

like image 732
Gammer Avatar asked Sep 18 '18 19:09

Gammer


2 Answers

Your problem is here:

node = document.querySelectorAll('[data-tippy]');
let id = node[0].dataset.postid;

Instead of selecting currently hovered element, you always select the same element (node[0]).

You can use the callback functions argument to get the current element clicked (onShow first argument contains a reference to an object that has reference to the original element, in my example - tip.reference). Example below:

tippy.setDefaults({
  arrow: true,
  delay: 240,
  theme: 'my-tippy',
  onShow(tip) {
    console.log('Post id: ' + $(tip.reference).data('postid'));
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/tippy.js@3/dist/tippy.all.min.js"></script>
<button data-tippy="Tooltip" data-postId="1">Post 1</button>
<button data-tippy="Another tooltip" data-postId="2">Post 2</button>
<button data-tippy="Another tooltip" data-postId="3">Post 3</button>
like image 126
vicbyte Avatar answered Sep 25 '22 08:09

vicbyte


this is because keyword const creates a read-only variable.

Constants are block-scoped, much like variables defined using the let statement.

The value of a constant cannot change through reassignment, and it can't be re-declared.

you have to change it to var or let, because it needs to be mutable (which const isn't).

The var statement declares a variable, optionally initializing it to a value.

The let statement declares a block scope local variable, optionally initializing it to a value.

theory aside, you have to change const tip to var tip - in order to update and/or destroy it.

according to the following markup - which is still a little narrow, because it is not the rendered HTML output of one whole post's markup, as it would be required to reproduce the issue in a reliable manner:

<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>

one could (probably, within the scope of the event source) obtain the id alike:

var id = parseInt($(this).data('postId'));

the most common method to handle ids would be to use attribute id (eg. with a post_id alike post_45) of the whole post's node in combination with

var id = parseInt($(selector).attr('id').replace('post_', ''));

the bottom line is, that without the complete markup of a single post, I can only hint for syntax alike $(this).parent().parent()..., which may be required in order to get a handle, which would need to be selected relative to the event source.

like image 38
Martin Zeitler Avatar answered Sep 25 '22 08:09

Martin Zeitler