Home > OS >  Loading order for multiple libraries (isotope boostrap jquery json data)
Loading order for multiple libraries (isotope boostrap jquery json data)

Time:12-12

I'm trying to make tooltips appear when hovering over an image in isotope cards, for that I wanted to use the boostrap library. But it only works with hardcoded elements in the html not for elements loaded from an js script. What am I missing?

The order in which I load the libraries are:

<head>
  <!-- tooltips background -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <link rel="stylesheet" href="custom_style.css">

  <!-- isotope library and jquery -->
  <script src="https://code.jquery.com/jquery-3.6.1.min.js" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" crossorigin="anonymous"></script>

  <!-- boostrap for tooltips -->
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" crossorigin="anonymous"></script>
  
  <script src="custom_scripts.js">/script>
</head>
<body> 
  ...
  some hardcoded code that works and shows the tooltip with the boostrap and isotope logic
  ...
</body>

And in custom_scripts.js

$(document).ready(function() {


   function isotopeCode(){
      ...
      isotope logic
   }

   // ========= load data from two json files =========
   let json = {};
   var ability_translation = {};

   $.getJSON("ability_translation.json", function(traducciones) {
      ability_translation = traducciones;
   });

   $.getJSON("data.json", function(datos){
      ...
      some logic
      ...
   }).then(() => isotopeCode());

});

I apologize in advance if the problem is duplicated but I could not find it on stackoverflow.

I tried to change the order in which the elements are loaded in different ways (in the html) but all without success (even put some parts at the end of the body)

What I am trying to achieve is that after the json elements are loaded (having loaded the cards tooltips in the DOM) the boostrap library is applied, so it can show the tooltip with the characteristic boostrap black background along with the posibilities of this library. So i want that Boostrap is the last thing to load (If I am not mistaken the boostrap logic only works after the json elements have been loaded into the DOM)

CodePudding user response:

If I understand your issue correctly, event listeners that are added to elements on the page when the document is ready can't be added to elements that are not yet on the page. This is a common problem. You'll need to add handlers to elements loaded after the original page load manually. Or consider a different approach entirely.

Update:

I think your issue is mostly one of timing. It appears that $.getJSON is async, and you're calling it twice. What you need to do is initialize your tooltip code after both of these return. There are patterns already created for us to execute after async code, and that is usually using promises.

If you want to execute something after multiple async calls you should consider reaching for Promise.all() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

The api for promises has been standardized at this point, but I'm not sure that jQuery implements the standard. Mosty developers have moved on from jQuery these days, as many of the solutions it offered are better solved by a transpiling step common to modern JS development.

But to offer a potential solution using the code you have (instead of or before trying promises) why not try the following, which basically manually wires up the things you want to do in the order you want to do them. Bear in mind that this type of manual wiring up doesn't scale well, and also defeats some of the power of async requests by serializing them:

function isotopeCode(){
  ...
  isotope logic
}

function initTooltips(){
 $('[data-toggle="tooltip"]').tooltip()
}

$.getJSON("ability_translation.json", function(traducciones) {
  ability_translation = traducciones;
  $.getJSON("data.json", function(datos){
    ...
    some logic
    ...
    initTooltips() 
  })
});

If $.getJSON implements proper promises, the following is a better approach, or you might have to convert them to the fetch() api, and not use jQuery.

const promise1 = $.getJSON("ability_translation.json", function(traducciones) {
  ability_translation = traducciones;
});

const promise2 = $.getJSON("data.json", function(datos){
  ...
  some logic
  ...
});

Promise.all([promise1, promise2]).then((values) => {
  isotopeCode();
  initTooltips();
});

  • Related