web-dev-qa-db-fra.com

Actualisation / mise à jour automatique de la table à l'aide de jQuery ajax à l'aide de fichiers json ou html

Alors @SOF,

J'ai essayé de faire en sorte que ma page Web sur les notes scolaires, les résultats, les notes projetées, etc. dispose d'une fonction de mise à jour automatique afin que les données de la page soient actualisées lorsque de nouvelles données arrivent via l'utilisation de jquery et ajax ainsi qu'une "vue unique" pour les classes.

Mon principal problème est que je ne parviens pas à faire fonctionner correctement toute forme de rafraîchissement/chargement ajax, je peux produire ma sortie dans des fichiers json ou html simples, pour mes besoins, je pense que le json serait mieux mais je ne suis pas sûr.

Ma page Web a un assistant de navigation en haut à gauche, qui est un menu déroulant qui est rempli via une liste trouvée par une "recherche" pour <a id="CLASS1" optionname="CLASS 1"></a> qui peut être trouvé dans le tableau, mais si besoin est, je peux le remplir en dehors du tableau si besoin est.

Je souhaite idéalement pouvoir modifier la liste déroulante, nous avons donc dans cet exemple un total de 8 options comprenant - Select Class -, Class 1, Class 2, Class 3, Class 4, Class 5, All Updating, All Non-Updating

Toutes les mises à jour

  • Cette option chargera toutes les classes dans une page visualisable html et mettra à jour chaque classe toutes les 30 secondes (je dis que chaque classe car certaines classes peuvent se mettre à jour en une heure, à une heure différente certaines autres classes peuvent se mettre à jour) donc il faudrait comparer et si différent alors mettre à jour?

Tous sans mise à jour

  • Cette option chargera toutes les classes dans une page visualisable html mais ne sera pas mise à jour à moins que l'utilisateur ne clique sur une classe différente (en utilisant le menu déroulant) puis clique retour...

Classe 1, classe 2, classe 3 ... etc (chargement individuel/vue unique)

  • Cette option chargera les données d'une seule classe dans une page visualisable html et mettra à jour cette classe spécifique toutes les 30 secondes, dans un article précédent un utilisateur nommé Gaby aka G. Petrioli a donné un exemple qui est assez proche de ce dont j'ai besoin mais le membre n'est jamais revenu vers moi: http://jsfiddle.net/u7UkS/ 4 /

Liens vers toutes les données

HTML - http://Pastebin.com/raw.php?i=0PNQGMmn

CSS - http://Pastebin.com/raw.php?i=4H5GHv15

JSON - http://Pastebin.com/raw.php?i=xk860dBN

Page de classe unique - http://Pastebin.com/raw.php?i=HvpaVhG6

JSFiddle - http://jsfiddle.net/kHtuQ | http://jsfiddle.net/kHtuQ/show

Article précédent avec quelques exemples ajax de certains membres: Anchor Cycler/Dropdown pour importer périodiquement les données des classes de l'école


Voici un exemple pour montrer à peu près ce qu'il y a dans chaque "classe" Remarque Classe = Classe scolaire

Exemple de table super mince:

<table id="gradient-style">
    <tbody>
        <thead>
            <tr>
                <th scope="col"><a id="CLASS1" optionname="CLASS 1"></a>Class</th>
            </tr>
        </thead>
        <tr><td>Class 1</td></tr>
    </tbody>
    <tfoot>
            <tr>
                <th class="alt" colspan="34" scope="col"><a id="KEY"></a><img class="headimager" src="http://placehold.it/250x50"/></th>
            </tr>
            <tr>
                <td colspan="34"><em><b>Data</b> - Test</em></td>
            </tr>
    </tfoot>
</table>

Si quelqu'un pouvait aider, ce serait très apprécié et si vous êtes en mesure de commenter, faites-le afin que je puisse continuer à apprendre.

Merci
Dennis S

26
Dennis Sylvian

utiliser ajax est très simple,
Je vous recommande d'utiliser le type de données HTML pour cela car vous avez une table dans votre conteneur,
il y a une documentation api ici => http://api.jquery.com/jQuery.ajax/
voici un violon que j'ai fait pour vous => http://jsfiddle.net/sijav/kHtuQ/19/ ou http://fiddle.jshell.net/ sijav/kHtuQ/19/show /

J'ai mis du code ajax dans une fonction nommée updateClass (url) qui correspond à l'url à obtenir et il ajoutera le conteneur avec le code HTML qu'il obtient =>

function updateClass(url){
    $.ajax({
        url: url,
        dataType: "HTML",
        error: function(msg){
            alert(msg.statusText);
            return msg;
        },
        success: function(html){
            $("#container").html(html);
        }
    });
}

J'ai ajouté une refreshClass qui actualise toute la classe de conteneur, =>

function refreshClass(){
            updateClass("http://fiddle.jshell.net/sijav/mQB5E/5/show/"); //update the class
}

et changé sur le sélecteur de changement en code ci-dessous =>

var classUpdateI; //stands for our interval updating class
$(".class-selector").on("change",function(){
    if (classUpdateI!=null)clearInterval(classUpdateI); //If the selector changed clear the interval so the container won't be update on it's own
    if(this.value == "")
        return; // if the value is null don't do anything
    else if(this.value == "allclassnup"){
        refreshClass(); //if the value is allclassnup which is stands for All Non-Updating just refresh the whole class 
    }
    else if(this.value == "allclassup"){
        refreshClass(); //if the value is allclassup which is stands for All Updating refresh the whole class and set an interval for thirty second (look for 30*1000)
        classUpdateI = setInterval(refreshClass,30*1000);
    }
    else //else then it's a simple class value, just simply update the current class
        updateClass(this.value);
})

J'espère que ça aide ;)
[~ # ~] éditez [~ # ~] : édité pour qu'il puisse obtenir une grande table (pas la générer!) et tout -la mise à jour sera mise à jour dans un intervalle de 30 secondes
AnotherEDIT : Croyez-le ou non, j'ai répondu à toutes vos questions!
FIDDLE DE TRAVAIL: http://jsfiddle.net/sijav/kHtuQ/39/ ou http://fiddle.jshell.net/sijav/kHtuQ/39/ show /
1 c'est parce que ça n'a été fait que pour le dernier html, pour le nouveau on devrait le refaire! mettez donc toute la fonction $('tr').click() dans une autre fonction et appelez-la si nécessaire.
- voulez-vous que cela fonctionne pleinement? c'est un peu compliqué mais ça peut marcher avec un peu de changement de code! que je vais vous montrer, bien voici l'algorithme que nous devrions mettre la classe actuelle sur le sélecteur de classe changer en cookie et ensuite nous pouvons le lire chaque fois que nous actualisons ou rechargeons la page et mettons la classe sélectionnée nécessaire et ainsi de suite ...
mais dans la conception de code ici, je l'ai fait pour que ça marche,
J'ai d'abord créé une variable globale appelée FirstTimeInit = true; juste pour être sûr que nous soyons sur la première fois de chargement de la page ou non, ensuite j'ai mis la boucle for qui met les choses en surbrillance lors du chargement de la page pour une fonction appelée selectSelectedClass, pourquoi? parce que nous devons l'appeler plusieurs fois, Troisièmement, j'ai ajouté une instruction if pour être sûr de pouvoir lire les cookies, puis changer les choses en surbrillance et la classe actuelle également, voici le code:

if(readCookie("CurrentClass")) //if we can read coockie
    $(".class-selector").val(readCookie("CurrentClass")).change(); //change it's value to current cookie and trigger the change function
else{ // else
    selectSelectedClass(); //select those which was highlighted before
    trClick(); //make things clickable
    FirstTimeInit = false; //and turn of the first time init
}

Ajout d'un cookie de création sur les changements de valeur du sélecteur => createCookie("CurrentClass",$(".class-selector").val(),1);
et enfin changer le succès pour obtenir Ajax à ce

        success: function(html){
            $("#container").html(html + '<a id="KEY"></a>'); //the html container changer with adding extra id , I'll explain it later it's for your second question
            if(FirstTimeInit){ //if it is First Time then
                selectSelectedClass(); //highlight which was highlighted after put the correct html
                FirstTimeInit = false; // turn of the first time init
            }
            else //else
                for (var i=0;i<($("table").children().length);i++){
                    if(readCookie(i))
                        eraseCookie(i); //erase every cookie that has been before because the table is now changed and we're going on another table so old cookie won't matter
                }
            trClick(); //make things selectable!
        }

Aussi pour le rendre sans bug, j'ai changé la refreshClass pour la tourner en premier lorsque la classe sélectionnée est tout ou elle est nulle car alors nous avons toutes les classes et avons besoin de ces cookies! voici donc le code:

function refreshClass(){
    if(readCookie("CurrentClass")=="allclassnup"||readCookie("CurrentClass")=="allclassup"||readCookie("CurrentClass")==null)
        FirstTimeInit = true;
    updateClass("http://fiddle.jshell.net/sijav/mQB5E/5/show/");
}

2 le <a id="TOP"></a> Doit être avant le conteneur, le <a id="KEY"></a> Doit être généré à la fin du conteneur après avoir mis du html sur le conteneur. donc $("#container").html(html + '<a id="KEY"></a>');

3 Le bouton Suivant et Précédent a été conçu pour une conception précédente non ajax, il a maintenant besoin d'une solution différente! voir par exemple ces codes simples

$("#PreviousClass").click(function(){//on prev click
    $(".class-selector").val($(".class-selector option:selected").prev().val()).change() //change the value to the prev on and trigger the change
});

$("#NextClass").click(function () {//on next click
    $(".class-selector").val($(".class-selector option:selected").next().val()).change() //change the value to the prev on and trigger the change
});

4 Oui, il est possible que vous changiez votre clé en haut et en bas pour ces codes et vous êtes prêt à aller =>

currentClass=0;
$("a.TOPJS").click(function () {
    if(currentClass>0){
        currentClass--
        scrollToAnchor('CLASS'+currentClass);
    }
});

$("a.KEYJS").click(function () {
    if($("a[id='CLASS" + currentClass + "']")[0]!=undefined){
        currentClass++
        scrollToAnchor('CLASS'+currentClass);
    }
    else
        scrollToAnchor('CLASSMAX');
});

Godd Luck

Une autre demande EDIT: (j'espère que ce sera la dernière!)
Violon de travail : http://jsfiddle.net/sijav/kHtuQ/42/ ou - http://fiddle.jshell.net/sijav/kHtuQ/42/show/
bien que vous n'aimiez pas changer la classe lors de l'actualisation en une qui s'y trouvait, j'ai supprimé cela, et mieux j'ai ajouté quelques codes pour avoir des classes dans les cookies, car les cookies ne sont pas des arbres, il y en a genre de conditions, la classe est lue à partir du dernier caractère du sélecteur de classe donc assurez-vous d'avoir le numéro de classe au dernier caractère comme -> Class number ***5*** le numéro 5 sera lu pour le sélecteur de classe!
[~ # ~] éditez [~ # ~] : optimisez la classe next et prev voyez http: // jsfiddle .net/sijav/kHtuQ/46 /
[~ # ~] modifier [~ # ~] : selon le commentaire demandé,
.
.

classUpdateI = setInterval(function(){updateClass(this.value,parseInt(a.charAt(a.length-1),10));},30*1000);

2) Manquants?! Je ne trouve pas votre deuxième question!
3) Eh bien, ... trclick doit changer ... en =>

function trClick(tIndex){ //tIndex would be classnumber from now on
    if (tIndex == -1){ //if it is all updating or all non updating
        $("tr").click(function(){ //do the previous do
            $(this).toggleClass('selected').siblings().removeClass('selected');
            if(readCookie($(this).parent().index("tbody"))){
                if(readCookie($(this).parent().index("tbody"))==$(this).index())
                    eraseCookie($(this).parent().index("tbody"));
                else{
                    eraseCookie($(this).parent().index("tbody"));
                    createCookie($(this).parent().index("tbody"),$(this).index(),1);
                }
            }
            else
                createCookie($(this).parent().index("tbody"),$(this).index(),1);
        });
    }
    else{ //else
        $("tr").click(function(){ //on click
            $(this).toggleClass('selected').siblings().removeClass('selected');//do the toggle like before
            if(readCookie(tIndex)){ //if you can read the CLASS cookie, not the current index of table because our table has only one row
                if(readCookie(tIndex)==$(this).index()) //as before if we selecting it again
                    eraseCookie(tIndex); //just erase the cookie
                else{ //else
                    eraseCookie(tIndex); //select the new one
                    createCookie(tIndex,$(this).index(),1);
                }
            }
            else
                createCookie(tIndex,$(this).index(),1); //else if we can't read it, just make it!
        });
    }
}

et quand nous l'appelons sur le succès Ajax, nous devons l'appeler avec classNumber => trClick(classNumber);
Dernier violon fonctionnel:http://jsfiddle.net/sijav/ kHtuQ/53 / ou http://fiddle.jshell.net/sijav/kHtuQ/53/show/

Bonne chance

22
Sijav

Honnêtement, j'ai du mal avec le code que vous avez publié, principalement parce que je ne comprends pas l'exemple JSON. Si vous allez stocker du HTML plat en tant que valeurs JSON, il est plus logique de simplement $.ajax le HTML dans le DOM plutôt que l'encodage, l'analyse et l'insertion JSON. Cela étant dit, je vais supposer que le JSON n'était pas un exemple réaliste et qu'il faudra plus de forme:

{ class_name: "Class 1", description: "Blah Blah Blah" }

Avec cette hypothèse à l'esprit, cet exemple bien documenté mais non testé devrait vous orienter dans la bonne direction. Essentiellement, je fais ce qui suit:

  • Définir un modèle HTML
  • Créez une fonction de modèle simple pour transposer les valeurs JSON dans le modèle HTML
  • Configurez un intervalle pour interroger le serveur pour les nouvelles données en utilisant setInterval appelant une fonction qui transmet un horodatage de la dernière fois que nous avons demandé à votre JSON de générer un script côté serveur en utilisant getJSON

Voici mon exemple, faites-le moi savoir si vous avez des questions.

<script>
//  I wrapped this in a self-invoking anonymous function to prevent adding new global variables
(function(){
    var SECONDS_TO_POLL = 3
    ,   $parent_node = $('#node-to-append-to')
    ,   last_timestamp = null // this will be a timestamp passed to the server
    ,   template = '<table id="gradient-style"> \
            <tbody> \
                <thead> \
                    <tr>
                        <th scope="col"><a id="{ident}" optionname="{class_name}"></a>Class</th> \
                    </tr> \
                </thead> \
                <tr><td>{class_name}</td></tr> \
            </tbody> \
            <tfoot> \
                <tr> \
                    <th class="alt" colspan="34" scope="col"><a id="KEY"></a><img class="headimager" src="{image}" /></th> \
                </tr> \
                <tr> \
                    <td colspan="34"><em><b>Data</b> - Test</em></td> \
                </tr> \
            </tfoot> \
        </table>';

    /**
    *   simple templating function
    *   @param template String template using bracket vars (e.g. <h1>{message}</h1>)
    *   @param values Object literal (e.g. {message: "Hello"})
    *   @return Rendered HTML template
    */
    var render_template = function(template, values) {
            values = values || {};
            return template.replace(/{([^{}]*)}/g, function(bracketed, clean){
                  var object_value = values[clean];
                  return ['string', 'number'].indexOf((typeof object_value)) > -1 ? object_value : bracketed;
            });
        };

    // this is our polling function, will retrieve the JSON from the server, convert to HTML using template and render to the DOM
    var poller = function(){
        // load the JSON and pass a GET var telling the server what timestamp to query from (e.g. WHERE data.timestamp > last_timestamp)
        $.getJSON('/path/to/json?last_retrieved='+last_timestamp, function(data){
            // render the new data into our HTML template
            var html = render_template(template, data);
            // append the result to the parent DOM node
            $parent_node.append(html);
        })
        // get a current timestamp so that we can limit the server results to those 
        last_timestamp = new Date().getTime();
    }

    // retrieve new results every N seconds
    setInterval(poller, SECONDS_TO_POLL*1000);
})()
</script>

Aussi, juste pour mettre un arc dessus, si vous venez de renvoyer du HTML depuis le serveur, vous pouvez (pour la plupart) simplement remplacer $.getJSON avec $.get, renonce à tout le rendu du modèle côté client et ajoute simplement la réponse au DOM

(function(){
    var SECONDS_TO_POLL = 3
    ,   $parent_node = $('#node-to-append-to')
    ,   last_timestamp = null // this will be a timestamp passed to the server

    // this is our polling function, will retrieve the HTML from the server and render to the DOM
    var poller = function(){
        // load the HTML pass a GET var telling the server what timestamp to query from (e.g. WHERE data.timestamp > last_timestamp)
        $.get('/path/to/server?last_retrieved='+last_timestamp, function(html){
            // append the result to the parent DOM node
            $parent_node.append(html);
        })
        // get a current timestamp so that we can limit the server results to those 
        last_timestamp = new Date().getTime();
    }

    // retrieve new results every N seconds
    setInterval(poller, SECONDS_TO_POLL*1000);
})()
4
Rob M.

La meilleure façon de résoudre votre problème consiste à utiliser une bibliothèque de liaisons telle que knockout. Avec cela, vous séparez vos données et votre vue et n'avez qu'à vous soucier de la façon dont vous mettez à jour les données, la vue sera mise à jour automatiquement. C'est ce avec quoi vous semblez actuellement vous battre.

C'est pourquoi j'ai fait un petit échantillon en générant une liste et en mettant à jour les données en l'interrogeant constamment (en utilisant un faux service qui renvoie toujours les mêmes données qui changent au hasard).

Voici l'exemple que j'ai fait en utilisant knockout: Veuillez consulter la page de documentation knockout: http://knockoutjs.com/documentation/introduction.html

HTML: définir un tableau simple avec en-tête et contenu

<table style="width: 100%" border="1">
    <thead>
        <tr>
            <td>
                <p><b>Classes</b>   
                </p>
            </td>http://jsfiddle.net/yBat5/#fork
            <td>
                <p><b>Childs</b>
                </p>
            </td>
        </tr>
    </thead>
    <tbody data-bind="foreach: Classes">
        <tr>
            <td>
                <p data-bind=" text: Class"></p>
            </td>
            <td>
                <p data-bind=" text: Child"></p>
            </td>
        </tr>
    </tbody>
</table>

JavaScript:

$(function () {
   // define a ViewModel for your data
    function ViewModel() {
        this.Classes = ko.observableArray([{
            "Class": "test",
                "Child": "Max"
        }, {
            "Class": "test2",
                "Child": "Walter"
        }]);
    }

    var vm = new ViewModel(),
        dummyData = [];

    // create a lot of dummy data sets
    for (var i = 0; i < 1000; i++) {
        dummyData.Push({
            "Class": "test " + i,
                "Child": "Child" + i
        })
    }

    // constantly poll for new data
    // JS fiddle implements a simple echo service, which we can use
    // to simulate data changes we change a rendon number
    function poll() {
        $.ajax({
            "url": "\/echo\/json\/",
                "type": "POST",
                "data": {
                "json": JSON.stringify(dummyData),
                    "deley": 3
            },
                "success": function (data) {
                vm.Classes(data);

                // poll again (3 seconds so we see how fast the update is)
                setTimeout(poll, 300);

                    // change a random entry to see that data changes
                var randomnumber=Math.floor(Math.random()*1000);
                    dummyData[randomnumber].Child = "Child"  +randomnumber +" changed"
            }
        });
    }

    poll();

    // apply it to the page, knocout now does the binding for you
    ko.applyBindings(vm);
});

Violon: http://jsfiddle.net/yBat5/3/

1
Stefan