8

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.

Gammer
  • 5,453
  • 20
  • 78
  • 121
  • why is everything declared using `const`? Every variable in your code i mean. –  Sep 23 '18 at 12:44
  • 1
    +1, But turns out the ID i am sending in the ajax request sends the only last one Thats why the tooltip comes the same, My bad there. How can i get tooltip data attribute with $(this), To send unique ID with each request ? – Gammer Sep 23 '18 at 12:46
  • @Gammer you should add some markup, if you wish accurate example code - because the question does not really indicate, against what the code would run - therefore only permitting generic answers. – Martin Zeitler Sep 23 '18 at 13:07
  • @martinZeitler Updating question. – Gammer Sep 23 '18 at 13:08
  • @martinZeitler question updated – Gammer Sep 23 '18 at 13:10
  • @vicByte Question updated – Gammer Sep 23 '18 at 13:10
  • if the `span` element is the one that triggers the tooltip on hover then grab the id of the tooltip showing by the `aria-describedby` attribute on `span` element. You may check what i mean in this fiddle http://jsfiddle.net/vo1sxzbp/3/, hover over a button while inspecting the element on your browser. I hope this is what you mean in your comment. @Gammer –  Sep 23 '18 at 13:30

2 Answers2

6

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>
vicbyte
  • 3,690
  • 1
  • 11
  • 20
  • Perfect... Solved, Thanks a million, Sadly can't upvote your answer a million times. I will accept the answer as soon as it lets me accept. – Gammer Sep 23 '18 at 13:38
  • Glad i helped with your issue. :) – vicbyte Sep 23 '18 at 13:39
  • In the mean time, Let me ask you something about it. Currently this works for content which loads for the first time. But It doesn't works if the html gets appends, Means when the `` appends dynamically the tooltip does not shows up. What can be done with that ? – Gammer Sep 23 '18 at 13:40
  • @Gammer If i understood you right, when you dynamically add new buttons to the page, tips no longer shows on them? – vicbyte Sep 23 '18 at 13:43
  • This is probably due to how tippy does initialization (adds tips only to the elements currently on page). You could try initializing the new elements after you add them (for example load them with an additional class/data-attribute -> initialize that class -> remove the extra class). – vicbyte Sep 23 '18 at 13:49
  • I will try that. – Gammer Sep 23 '18 at 13:52
1

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.

Community
  • 1
  • 1
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • +1, But turns out the ID i am sending in the ajax request sends the only last one Thats why the tooltip comes the same, My bad there. How can i get tooltip data attribute with `$(this)`, To send unique ID with each request ? – Gammer Sep 23 '18 at 12:45
  • 2
    I don't think `const` would be a problem though. You cannot reassign the variable itself, but it's entirely fine to reasign a property inside it (update it). – vicbyte Sep 23 '18 at 12:47
  • @martinZeitler it says `Uncaught ReferenceError: selector is not defined` with `$(selector).data("tooltip")` – Gammer Sep 23 '18 at 12:53
  • @Gammer `selector` is a commonly used pseudo-variable for all kinds of DOM selectors - while within the scope of a `tooltip` event, it would be `this`, which refers to the source of the event - while outside of that scope, it rather would be a selector string. – Martin Zeitler Sep 23 '18 at 12:56
  • `Uncaught ReferenceError: selector is not defined`. – Gammer Sep 23 '18 at 13:06
  • @MartinZeitler Updating my demo here, cause its related to this answer: http://jsfiddle.net/gj4vymze – vicbyte Sep 23 '18 at 13:12