Menu
I cannot get this to work properly. Sometimes it works. Sometimes it fails. The menu is created and ready. But refuse to show up (randomly) in tippy container.
[url=https://postimages.org/][img]https://i.postimg.cc/RZx0GJXg/tippy.png
Sometimes i get it to work by delaying by an alert:
[url=https://postimages.org/][img]https://i.postimg.cc/vHvGb2Qd/alert.png
What am I doing wrong?
>@Sempervivum#1644207 Fix it by initializing tippy in the callback of the XMLHttpRequest.
``<i>
</i>function api3get() {
var url = "https://api3.go4webdev.org/" + mod + '/all';
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = 'json';
xhr.onload = function() {
if (xhr.readyState === 4) {
filltable(this.response);
tippy('td.status', {
theme: 'custom',
trigger: 'click',
content: document.querySelector('.tippystatus').innerHTML,
allowHTML: true,
arrow: false,
appendTo: 'parent',
interactive: true
});
tippy('td.more', {
theme: 'custom',
trigger: 'click',
content: document.querySelector('.tippymore').innerHTML,
allowHTML: true,
arrow: false,
appendTo: 'parent',
interactive: true
});
}
};
xhr.send();
}<i>
</i>
``
``<i>
</i>getstatus();
function getstatus() {
fetch('https://api3.go4webdev.org/status/all')
.then((response) => response.json())
.then(fillpopstatus)
.catch(error => console.log(error))
}<i>
</i>
`</CODE>
This request has to be ready before initializing tippy. I confirmed this by use of the debugger: When stopping at this line:<br/>
<C>
tippy('td.status', {
</C><br/>
and viewing what<br/>
<C>
document.querySelector('.tippymore').innerHTML
`
is returning, the ul is empty.
>@Sempervivum#1644221 This request has to be ready before initializing tippy.
then
</C> callback of the fetch request:
<CODE>
`<i>
</i>getstatus();
function getstatus() {
fetch('https://api3.go4webdev.org/status/all')
.then((response) => response.json())
.then(data => {
fillpopstatus();
// Template for the popup menu is ready now,
// init tippy here
})
.catch(error => console.log(error))
}<i>
</i>
``>@Sempervivum#1644223 Initialize tippy in the then callback of the fetch request:
``<i>
</i>getmore();
function getmore() {
fetch('https://api3.go4webdev.org/action/all')
.then((response) => response.json())
.then(fillpopmore)
.catch(error => console.log(error))
}
let popmore = document.querySelector(".popmore");
let fragment2 = new DocumentFragment()
function fillpopmore(data){
data.forEach(function(element) {
var start =
<svg class="std"> <use xlink:href="#
var end =
"/></svg>
var li = document.createElement('li')
li.setAttribute('data-action',element.action_id)
li.innerHTML = (start + element.action_id+ end + element.action_en)
fragment.appendChild(li)
})
popmore.appendChild(fragment)
}<i>
</i>
`</CODE>
and the init of tippy:
<CODE>
`<i>
</i>api3get();
function api3get() {
let url = "https://api3.go4webdev.org/" + mod + '/all';
fetch(url)
.then((response) => response.json())
.then(filltable)
.then(tippy)
.catch(error => console.log(error))
}
function tippy() {
tippy('td.status', {
theme: 'custom',
trigger: 'click',
content: document.querySelector('.tippystatus').innerHTML,
allowHTML: true,
arrow: false,
appendTo: 'parent',
interactive: true
});
tippy('td.more', {
theme: 'custom',
trigger: 'click',
content: document.querySelector('.tippymore').innerHTML,
allowHTML: true,
arrow: false,
appendTo: 'parent',
interactive: true
});
}<i>
</i>
``
> Unfortunately I cannot find this alert. Give me a hint, which file?
popup.js
>@Sempervivum#1644225 Unfortunately I cannot find this alert. Give me a hint, which file?
popup.js
``<i>
</i>function getstatus() {
fetch('https://api3.go4webdev.org/status/all')
.then((response) => response.json())
.then(fillpopstatus)
.catch(error => console.log(error))
}<i>
</i>
`</CODE>
Ajax works asynchronously, this means, the request is sent to the server, then, <STRONG>**after a short delay**</STRONG>, the response from the sever arrives. Obviously, when you initialize tippy, this has not yet happened and the <C>
ul
</C>s are still empty.<br/>
When you add the alert, it takes a fairly long time until the user reacts and during that time the response has arrived and the <C>
ul
`s are populated when initializing tippy.
ul
`>@Sempervivum#1644229 If so you will have to wait for both events
``<i>
</i>var getstatus = async function () {
var response = await fetch('https://api3.go4webdev.org/status/all');
var json = await response.json();
fillpopstatus(json)
};
let popstatus = document.querySelector(".popstatus");
let fragment = new DocumentFragment()
function fillpopstatus(data) {
data.forEach(function(element) {
let start =
<svg class="std hide"><use xlink:href="#status
let end =
"/></svg>
var li = document.createElement('li')
li.setAttribute("data-action", element.status_id)
li.innerHTML = (start + element.status_id + end + element.status_en)
fragment.appendChild(li)
})
popstatus.appendChild(fragment)
}
getstatus();<i>
</i>
``
>And it seems to work **almost** every time.
``<i>
</i>var getAll = async function () {
var responseMore = await fetch('https://api3.go4webdev.org/status/more');
var dataMore = await responseMore.json();
var responseStatus = await fetch('https://api3.go4webdev.org/status/all');
var dataStatus = await responseStatus.json();
var responseTable = await fetch('url-for-table');
var dataTable = await responseTable.json();
// now the data from all responses is ready, we can go ahead
// and create the elements:
fillpopstatus(dataStatus);
fillpopstatus(dataMore);
filltable();
tippy();
};<i>
</i>
``
>@Sempervivum#1644249 Try to fetch all of them in one await function like this:
>@Sempervivum#1644249 Apparently there is no improvement.
``<i>
</i>const menuData = [
{url: 'https://api3.go4webdev.org/status/more', fct: fillmore},
{url: 'https://api3.go4webdev.org/status/all', fct: fillall},
// and so on
]<i>
</i>
``
>@Sempervivum#1644251 One might consider to use an array like this:
>@Sempervivum#1644253 Unfortunately I do not understand what you mean by "window" in this context.
``<i>
</i><!DOCTYPE html>
<html lang="en">
<head>
<script src="/js/for_this_window.js" defer></script> <---- corresponding array for this window
</head><i>
</i>
``
> An individual HTML/PHP file while having a global JS file for all of them?
window
</C> in terms of javascript is, say, the root object of all variables. Any variable can be accessed by <C>
window.variableName
`>@Sempervivum#1644260 window
``<i>
</i><!DOCTYPE html>
<html lang="en">
<head>
<script src="/js/menu.js">
<script src="/js/for_this_window.js" defer></script>
</head><i>
</i>
`</CODE>
for_this_window.js:
<CODE>
`<i>
</i>const menuData = [
{url: 'https://api3.go4webdev.org/status/more', fct: fillmore},
{url: 'https://api3.go4webdev.org/status/all', fct: fillall},
// and so on
];
createAll(menuData);<i>
</i>
``
>@Sempervivum#1644263 So in HTML or PHP file 1 you will include a js file specific for that file or window containing the array and a call for the function that creates the table and menus.
array = fetch(arrays for page X)
>@Sempervivum#1644271 Wouldn't it be sufficient to insert the menus into the HTML on the server?
var dataMore = await responseMore.json();
``<i>
</i>const data = <_?php echo json_encode($array_created_from_database); ?_><i>
</i>
``
>@Sempervivum#1644274 the menus statically but instead create it from the database on the server instead of fetching it by ajax.
> Another option is leaving the server side script as is but inserting the data directly into javascript via json.
> On the client side in javascript when PHP is used on the server:
>@Sempervivum#1644263 for_this_window.js:
``<i>
</i> async function build_menus() {
var menus = JSON.parse(json);
for (let i = 0; i < menus.length; i++) {
const item = menus[i];
let response = await fetch(item.value);
let json = await response.json();
let ok = window[item.key](json);
}
}
build_menus();<i>
</i>
``
>@Sempervivum#1644309 I was able to force the order by processing all requests in one async function:
``<i>
</i>var json =
[{
"key": "fillstatus",
"value": "https://api3.go4webdev.org/status/all"
}, {
"key": "fillaction",
"value": "https://api3.go4webdev.org/action/all"
}, {
"key": "filltable",
"value": "https://api3.go4webdev.org/tsk/all"
}]
async function build_menus() {
var menus = JSON.parse(json);
for (let item of menus) {
let response = await fetch(item.value);
let json = await response.json();
window[item.key](json);
}
}
build_menus();
/* ---------------------- */
var table = document.querySelector('table');
function filltable(data) {
for (let item of data) {
row = table.insertRow();
row.setAttribute("data-id", item.tsk_id)
r1 = row.insertCell(0);
r1.setAttribute("data-key", "tsk_subject");
r1.innerHTML = item.tsk_subject
row.insertCell(1).className = "status"
row.insertCell(2).className = "more"
}
tippy2()
}<i>
</i>
``
>there is a slight delay in the popup menu
>Determines if the positioning engine (powered by Popper.js) is created lazily. That is, it's only created when necessary upon showing the tippy for the first time.
If you need to access the popperInstance synchronously after creation, set this to false. Note that disabling this decreases performance considerably.
>@Sempervivum#1644464 Sorry for replying late, this thread lost focus on my screen.
> When testing the tooltips I notice that they pop up when I release the mouse. Maybe this is causing the illusion of a delay.
> There is a short animation (fade in) for the popup. The duration is 275ms for appearing. This might be set to 0.
> There is an option "lazy". The docs say:
>Not that obvious on Chrome.
>I cannot se any settings for this. Any tip?
animation
</C> for the type and <C>
duration
`0.1.9 — BETA 4.25