Retarder le refresh de l'affichage

a marqué ce sujet comme résolu.

Bonjour,

J'aurai voulu savoir si il était possible de "retarder" le refresh d'une page web utilisant du JavaScript.

J'ai un fonction JavaScript qui doit ouvrir et refermer des éléments d'un accordéon JQuery. Les accordéons sont bien rempli et cela est donc long (1-2s en visuel) et moche.

J'aurai simplement voulu que le JS modifie la page et ne montre le résultat qu'une fois toutes les actions effectué. (Peut être avec une icône de chargement par dessus, mais même pas obligé)

Merci à vous!

+0 -0

Si, il y en a une : activate()

Le problème vient du fait que j'utilise une fonction JS qui vient simuler l'utilisation de cet accordeon.

Pour être un peu plus clair, j'utilise un google chart des API google. Celui ci prend sa taille en fonction de la taille de l'élément conteneur, il me faut donc ouvrir chacun des élément de l’accordéon, initialiser le chart et refermer l’élément.

Du coups c'est long puisque tout les charts s'initialise et que l'affichage arrête pas de bouger.

Merci d'avoir pris le temps de venir m'aider.

+0 -0

Tu insère l'élément dans le DOM que quand tout est chargé ?

Titi_Alone

Ghé??.. Désolé je n'ai pas encore tout le vocabulaire, même si DOM me dit quelque chose effectivement.

Pour l'instant je créé l'accordeon, j'ouvre une partie, j'insère le chart, je referme la partie

J'utilise la fonction click()

+0 -0

Salut, il va nous falloir ton code, parce que sinon personne ne pourra t'aider correctement. :)

PS : quand je lis ça :

Désolé je n'ai pas encore tout le vocabulaire, même si DOM me dit quelque chose effectivement.

j'ai comme l'impression que tu as appris à utiliser jQuery sans connaître JavaScript, je me trompe ?

j'ai comme l'impression que tu as appris à utiliser jQuery sans connaître JavaScript, je me trompe ?

Antho

J'ai effectivement appris JS et JQuery sur le tas sans réel cours avant. A la base ce n'est pas mon domaine, mais il a bien fallu que quelqu'un s'y colle :/

voici mon code du coup, c'est un code basé sur Django:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{% block content %}
    <div class="row" style="margin-top: 50px;">
        <div class="col-sm-12" align="center">
            <div class="row" align="center">
                <div class="col-sm-4" style="border-right: 1px solid grey;"><strong>{% trans "Number of companies" %}</strong> <br><span style="font-size: 70px;">{{companies.count}}</span></div>
                <div class="col-sm-4" ><strong>{% trans "Number of founders" %}</strong> <br><span style="font-size: 70px;">{{founders.count}}</span></div>
                <div class="col-sm-4" style="border-left: 1px solid grey;"><strong>{% trans "Number of mentors" %}</strong> <br><span style="font-size: 70px;">{{mentors.count}}</span></div>
            </div>
        </div>
    </div>

<!-- Début de l'accordéon --->
<div id="accordion" style="margin-top: 50px;">
    {% for type, data in finances.items %}
    <h3 id="elem-{{type}}">{{type|capfirst}}</h3>
    <div id="{{type}}">
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
        //La div du chart
        <div id="chart_{{type}}"></div>
        //Son script associé
        <script type="text/javascript">
            google.load("visualization", "1", {packages: ["corechart", 'bar']});
            google.setOnLoadCallback(drawDualX);

            function drawDualX() {
                var data = google.visualization.arrayToDataTable([
                    ['{% trans "Companies" %}', '{% trans "Amount" %}'],
                    {% for company, ammount in data %}
                        ['{{company}}', {{ammount}}],
                    {% endfor %}
                ]);

                var options = {
                    height: data.getNumberOfRows() * 30,
                    hAxis: {
                        title: 'Ammount - {{type}}',
                        minValue: 0
                    },
                    bars: 'horizontal',
                    backgroundColor : 'none'
                };

                //Init elem for set height and width of the chart
                var elem = document.getElementById('elem-{{type}}');
                elem.click();

                var chart = new google.visualization.BarChart(document.getElementById('chart_{{type}}'));

                google.visualization.events.addListener(chart, 'ready', function () {
                    //Close elem
                    elem.click();
                });

                chart.draw(data, options);
            }
        </script>
    </div>
    {% endfor %}
</div>

<!-- Import pour JQUERY Accordeon -->
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

<script>
$(function() {
    $( "#accordion" ).accordion({
        collapsible: true,
        heightStyle: "content"
    });
});
</script>
{% endblock %}

Merci de votre temps en tout cas!

+0 -0

Premièrement, ton <script type="text/javascript" src="https://www.google.com/jsapi"></script> est dans la boucle for, ce qui veut dire que le script https://www.google.com/jsapi risque d'être appelé plusieurs fois ! Ton javascript est lui aussi dans la boucle, le navigateur fait donc plusieurs fois les mêmes opérations, ce qui est inefficace. Il faut donc mettre le JS à l'extérieur de la boucle ! Cela nécessitera quelques modifications du code, mais normalement ce sera beaucoup plus rapide qu'actuellement.

Par ailleurs, tu importes un peu plus loin jQuery, je pense que tu pourrais donc aussi l'utiliser pour ouvrir ton accordéon.

Je te laisse essayer ça ? :)

+0 -0

Je te laisse essayer ça ? :)

Situphen

J'ai sorti le :

1
<script type="text/javascript" src="https://www.google.com/jsapi"></script> 

Cependant pour le reste je ne peut pas sortir le JS car il se compose en fonction de variable de template Django.

Au grand maximum je peut le sortir, en faire une fonction avec des arguments que j’appellerai a chaque fois dans ma boucle. Mais du coups je reviens exactement au même niveau de lourdeur (un appel de fonction en plus..).

Ouverture des accordeon

Je pourrais effectivement les ouvrir et fermer en dehors de la boucle, mais puisque je ne fait qu'une ouverture et fermeture par boucle je ne pourrais pas abaisser le nombre d'appel quoi que je fasse.

De plus un seul accordeon ne peut être ouvert a la fois, hors si je sort les appel de ma boucle, je ne sais pas quand ouvrir ni quand fermer l'accordeon en traitement.

Merci de ton temps!

+0 -0

Il faut absolument séparer ton code JavaScript de ta template. Là tu vas galérer à maintenir ce système et tu vas avoir plusieurs éléments <script> (dont le code est quasiment identique) en plein milieu de ton html.

Une façon de faire beaucoup plus propre serait de faire une requête asynchrone grâce à XMLHttpRequest. Comme tu as jQuery de chargé, tu peux utiliser sa méthode ajax().

De plus, selon la documentation de Google, tu as une option height qui te permet de définir la hauteur de ton graphique (au lieu d'ouvrir et de fermer l'élément de l'accordéon).

Donc pour résumer :

  1. Tu sépares template et code JavaScript
  2. Tu te fais une méthode dans Django accessible en GET qui renvoie les données que tu veux (ici en l'occurence finances.items)
  3. Avec JavaScript, tu envoies une requête GET vers l'URL précédemment définie
  4. Une fois que Django t'as renvoyé les données, il te suffit, dans ta fonction de callback, de générer les charts dans chaque bloc (comme Django va te renvoyer un tableau, tu boucles simplement dessus en JS)
+0 -0

De plus, selon la documentation de Google, tu as une option height qui te permet de définir la hauteur de ton graphique (au lieu d'ouvrir et de fermer l'élément de l'accordéon).

Antho

La documentation précise que l'option height prend un nombre de pixel, c'est pour cette raison que je l'utilise déjà :

1
height: data.getNumberOfRows() * 30,

Cependant la largeur de mon site est dynamique et je ne peut pas dire au chart quel largeur il doit prendre. C'est pour cette raison que j'en suis venu a ouvrir et fermer mon accordeon.

Donc pour résumer :

  1. Tu sépares template et code JavaScript
  2. Tu te fais une méthode dans Django accessible en GET qui renvoie les données que tu veux (ici en l'occurence finances.items)
  3. Avec JavaScript, tu envoies une requête GET vers l'URL précédemment définie
  4. Une fois que Django t'as renvoyé les données, il te suffit, dans ta fonction de callback, de générer les charts dans chaque bloc (comme Django va te renvoyer un tableau, tu boucles simplement dessus en JS)

Antho

Même si je conçois qu'il peut être plus esthétique d'avoir mon JS en dehors de mon HTML, je ne suis pas sur que ta solution va améliorer le niveau de performance de cet affichage, au contraire je l'alourdit encore d'une requète Ajax et de l'utilisation d'une vue Django.

Je pense qu'ici, malgré que cela ne soit pas très esthétique, je suis beaucoup plus performant. Je me contente de lancer les script et économise une requète HTTP.

Il faut absolument séparer ton code JavaScript de ta template. Là tu vas galérer à maintenir ce système et tu vas avoir plusieurs éléments <script> (dont le code est quasiment identique) en plein milieu de ton html.

Antho

Je ne pense pas que cela soit lourd a maintenir, puisque la réplication ne se forme qu'au moment de l'affichage. Je n'aurais toujours qu'un seul JS a maintenir. Qu'il soit dans une requète Ajax ou dans le template, cela reste exactement le même morceau et donc les même problèmes de maintenance.

J'ai cependant déjà prévu d'externaliser ce code mais sous la simple forme d'une fonction JS. De manière a pouvoir l'appeler depuis d'autre template utilisant le même chart.

Merci d'avoir pris le temps de me lire =)

+0 -0

Déjà, de mon point de vue, c'est une aberration de privilégier la performance au détriment de la maintenabilité (le jour où tu n'utilises plus Twig comme moteur de template, ton code doit être adapté) et de la propreté de ton code, surtout dans ce cas-là où, je le maintiens, une requête asynchrone est bien plus adaptée.

Tu n'as normalement pas besoin d'une nouvelle vue, il suffit de renvoyer un tableau JSON sur lequel tu boucles dans ton callback. À chaque tour de boucle, tu génères un chart et tu l'insères à l'endroit adéquat.

À mon avis (mais je peux pas être tout à fait sûr), le temps de latence est surtout dû au fait que tu ouvres puis fermes l'élément au callback de la génération du chart courant. Simuler deux click pour pouvoir adapter la largeur d'un graphique, c'est pas ce qu'il y a de plus performant et efficace. Les graphiques de Google sont générés sous quelle forme ? Images, canvas ou SVG inline ?

+0 -0

À mon avis (mais je peux pas être tout à fait sûr), le temps de latence est surtout dû au fait que tu ouvres puis fermes l'élément au callback de la génération du chart courant. Simuler deux click pour pouvoir adapter la largeur d'un graphique, c'est pas ce qu'il y a de plus performant et efficace. Les graphiques de Google sont générés sous quelle forme ? Images, canvas ou SVG inline ?

Antho

Il sont au formats SVG.

Déjà, de mon point de vue, c'est une aberration de privilégier la performance au détriment de la maintenabilité (le jour où tu n'utilises plus Twig comme moteur de template, ton code doit être adapté) et de la propreté de ton code, surtout dans ce cas-là où, je le maintiens, une requête asynchrone est bien plus adaptée.

Tu n'as normalement pas besoin d'une nouvelle vue, il suffit de renvoyer un tableau JSON sur lequel tu boucles dans ton callback. À chaque tour de boucle, tu génères un chart et tu l'insères à l'endroit adéquat.

Antho

Bon tu a l'air d'y être farouchement attaché alors je veut bien ouvrir le sujet. Quels sont les risques de maintenabilité? Car personnellement je ne les vois pas.. Mais puisque tu a l'air assez sur de toi je ne suis pas fermer a passer par une Ajax pour peu que j'en comprenne le bon sens.

Il y a vraiment une chance que je change de moteur de template Django? Je travaille sur une plateforme assez simpliste, qu'est ce que d'autre moteur de template aurait de mieux?

+0 -0

Tu ne peux jamais être sûr que tu ne changeras pas de techno dans quelques mois ou années, et ça arrive même aux meilleurs (cf. Twitter qui est passé de Ruby à Java). En injectant des variables PHP directement dans ton code JavaScript client, tu crées une dépendance entre les technos, et ça, en terme de maintenabilité et de pérénnité du code, c'est déconseillé. :)

Le travail d'un développeur n'est pas seulement de fournir un code fonctionnel. Il doit aussi être le plus qualitatif possible pour tenir dans la durée et t'éviter de t'arracher les cheveux lorsque tu repasseras dessus. Après c'est toi qui vois. :p

En utilisant une simple requête ajax, tu t'en fous d'utiliser Django, Symfony2 ou NodeJS. Ton système est agnostique, JS récupérera toujours un tableau JSON, et point barre.

Maintenant, pour ce qui est de la largeur des graphiques. Je ne sais pas trop ce que fait jQuery UI sous le capot, mais est-ce que tu ne peux pas simplement donner une largeur de 100% (ou ce que tu veux) à tes éléments d'accordéon ? Si j'ai bien compris, les charts de Google prennent la largeur de l'élément parent pour la donner au graphique SVG.

Sinon j'ai trouvé cette démo qui montre comment adapter la largeur des graphiques lors du redimensionnement de ta fenêtre.

+0 -0

En utilisant une simple requête ajax, tu t'en fous d'utiliser Django, Symfony2 ou NodeJS. Ton système est agnostique, JS récupérera toujours un tableau JSON, et point barre.

Antho

Hum je vois, effectivement ça serait plus propre… Je vais m'y mettre.

Maintenant, pour ce qui est de la largeur des graphiques. Je ne sais pas trop ce que fait jQuery UI sous le capot, mais est-ce que tu ne peux pas simplement donner une largeur de 100% (ou ce que tu veux) à tes éléments d'accordéon ? Si j'ai bien compris, les charts de Google prennent la largeur de l'élément parent pour la donner au graphique SVG.

Sinon j'ai trouvé cette démo qui montre comment adapter la largeur des graphiques lors du redimensionnement de ta fenêtre.

Antho

J'ai déjà essayer en leurs donnant des width de 100%, rien a faire… C'est l'une des div produite par le chart de google qui décide de ce mettre en 840px.

Je viens de voir pour ta démo, mais non ça ne fonctionne pas avec les accordéons. En fait il se contente de relancer l'affichage du chart a chaque resize de la fenêtre.

Par contre c'est intéressant et ça marcherai dès que le problème d'accordeon serait résolu sans click().

+0 -0

Hum, par contre ça veut dire que si j'ai du texte a traduire au sein de mes tableaux je suis olbiger de passer par une traduction en JS ?

Apparemment c'est possible de le faire en JS a première vu mais ça va faire double emploi, et deux fois plus de traduction a maintenir.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte