11521 sujets

JavaScript, DOM et API Web HTML5

bonjour
j'ai un script inline qui ne peut fonctionner que si le script qui est devant leaflet.js en defer est complement chargé
comment faire pour mettre en defer un script inline, ou alors attendre que leaflet.js soit chargé
si vous avez des idees merci
@parsimonhi : du coup j'ai une question subsidiaire : vaut-il mieux placer un "defer" ou un `window.addEventListener + load` directement dans le fichier pour appeler la fonction ?

Je pose la question parce que moi, pour l'instant, je fais comme ceci :
window.addEventListener('load', () => myLeafletMaps())

J'ai vu circuler des graphs de ce genre, mais je ne comprends rien à ce charabia :

upload/1647882937-35007-kygka.png

De ce que je pense avoir compris il me semble que defer se lance lorsque le DOM est chargé, alors que `window.addEventListener + load` se lancerait après le chargement du dernier script, ce qui me semble plus pertinent...

... mais du coup tu me mets le doute, il faut peut-être que je teste pour voir.
Modifié par Olivier C (21 Mar 2022 - 22:48)
Modérateur
Bonjour,

Olivier C a écrit :
@parsimonhi : du coup j'ai une question subsidiaire : vaut-il mieux placer un "defer" ou un `window.addEventListener + load` directement dans le fichier pour appeler la fonction ?

Je pose la question parce que moi, pour l'instant, je fais comme ceci :
window.addEventListener('load', () => myLeafletMaps())


Déjà, on parle ici de 2 choses différentes, d'une part l'exécution complète du script, et d'autre part l'exécution de certaines de ses fonctions seulement.

Personnellement, je n'utilise pas defer dans le cas général. Je préfère mettre simplement dans le code html les scripts dans l'ordre de leur exécution et utiliser `window.addEventListener + DOMContentLoaded` ou `window.addEventListener + load` pour tout ce qui doit être exécuté après chargement de la page.

À noter que l'évènement 'load' survient non seulement après le chargement du DOM mais aussi après chargement des autres ressources nécessaires (scripts, images, feuilles de style, etc.) contrairement à l'évènement 'DOMContentLoaded' qui lui survient après le chargement du DOM mais éventuellement avant que toutes les autres ressources soient chargées.

À noter également qu'on peut très bien être amener à utiliser "defer" et un `window.addEventListener + load`

Si par exemple un script utilise des fonctions qui récupèrent le style des éléments du DOM, utiliser "defer" ne suffit pas pour être sûr que les feuilles de style seront déjà prises en compte au moment de l'exécution du script. Dans un tel cas, utiliser `window.addEventListener + load` est requis.

À noter enfin qu'il faut se méfier avec les formulaires, et en particulier ceux qui ont des champs qui se remplissent plus ou moins tous seuls. Tous les navigateurs ne font pas la même chose (tester avec l'un d'entre eux seulement peut ne pas suffire).

Amicalement,
@parsimonhi : Merci beaucoup d'avoir pris le temps d'écrire cette réponse très complète.

Bien amicalement.
Bonjour,

Il me semble qu'il serait possible de le faire de cette manière:
<script>
    document.addEventListener('DOMContentLoaded', function(event) {
        var leafletLoader = document.createElement('script');
        leafletLoader.src = 'leaflet.js';
        leafletLoader.onLoad = () => {
            // leaflet is loaded, do something
        }
        document.head.appendChild(leafletLoader);
    });
</script>


Mais j'ai une autre solution à proposer: utiliser LoadJs

C'est un gestionnaire de dépendances Javascript, je l'utilise dans tous mes projets depuis que je l'ai découvert. En résumé il permet de charger ce qu'on veut comme on veut, et de déclencher des callbacks en fonction des chargements.

Je précise à tout hasard que je n'ai aucun lien d'aucune sorte avec les auteurs.

Ici ça donnerait par exemple:

loadjs('leaflet.js', function() {
  /*  loaded */
});


ou encore:

loadjs('leaflet.js', {returnPromise: true})
  .then(function() { /* leaflet.js loaded */ })
  .catch(function(pathsNotFound) { /* didn't load */ });
@migli : Ça vaux le coup de télécharger une lib' pour ça ?

Par exemple, pour un élément présent sur la page comme ceci :
<div class="map" style="height: 50vh" data-name="Map 1" data-places="lesCoordonnees" data-zoom="18"></div>

Perso je n'appelle le script que si une classe CSS correspondante est présente sur la page en faisant comme ceci :
const getScript = (url, hook = 'footer') => new Promise((resolve, reject) => { // @see  https://stackoverflow.com/questions/16839698#61903296
 
  const script = document.createElement('script')
  script.src = url
  script.async = 1
  script.onerror = reject
  script.onload = script.onreadystatechange = function() {
    const loadState = this.readyState
    if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
    script.onload = script.onreadystatechange = null
    resolve()
  }
  if (hook == 'head') document.head.appendChild(script)
  else if (hook == 'footer') document.body.appendChild(script)
  else console.log('Error: the choice of the html tag for the hook is not correct.')
})

const getScripts = (() => {
  if (document.querySelector('[class*=validation]')) getScript('/scripts/formValidation.js')
  if (document.querySelector('[class*=accordion]')) getScript('/scripts/accordion.js')
  if (document.querySelector('[class*=map]')) getScript('/scripts/map.js')
  // etc...
})()

Modifié par Olivier C (24 Mar 2022 - 13:05)