简体   繁体   中英

How to Get XML file with Jquery and Display Elements in Random Order ONCE per load?

I have been trying to build a question and answer app with Ajax. I need help creating a particular function. I have created XML files with different questions and answers. The basic idea is to use the "get" function to (1) load an XML questions file and (2) use the "display" and "math.random" functions to display a random "question" element (the corresponding "answer" element will be shown at the same time, but hidden from view by Javascript.) This is the format of the XML files I am using. These nodes are enclosed by a parent node, Words..

<WordQuestions>
    <Question>Question1</Question>
    <Answer>Answer1</Answer>
</WordQuestions>

<WordQuestions>
    <Question>Question2</Question>
    <Answer>Answer2</Answer>
</WordQuestions>

I need to create a function that can choose a question & answer element at random from the XML file, show it to the user, but NOT show it again on subsequent clicks by the user. So, once a question is shown to the user, it needs to be removed from the list of questions to be shown to the user on the next click. Does anybody know how to do this?

I have created a similar function that works like a charm, but it is limited in that it is too random - a questions & answer element may never be selected to show to the user, or it could be selected a disproportionate number of times. The user needs to practice with all of the questions. Here is a stripped-down version of this function.

<script language = "javascript">


  function getCategory()
  {
    var XMLHttpRequestObject = false; 

    if (window.XMLHttpRequest) {
      XMLHttpRequestObject = new XMLHttpRequest();
      XMLHttpRequestObject.overrideMimeType("text/xml");
    } else if (window.ActiveXObject) {
      XMLHttpRequestObject = new 
        ActiveXObject("Microsoft.XMLHTTP");
    }


    if(XMLHttpRequestObject) {

    var P = document.LoadCategory.Load.value;
    if (P == "Category1") {XMLHttpRequestObject.open("GET", "Catgory1.xml", true)}
    if (P == "Category2") {XMLHttpRequestObject.open("GET", "Category2.xml", true)} 
    if (P == "Category3") {XMLHttpRequestObject.open("GET", "Category3.xml", true)}


      XMLHttpRequestObject.onreadystatechange = function() 
      { 
        if (XMLHttpRequestObject.readyState == 4 && 
          XMLHttpRequestObject.status == 200) { 
        var xmlDocument = XMLHttpRequestObject.responseXML;
        displayCategory(xmlDocument);
        } 
      } 

      XMLHttpRequestObject.send(null); 
    }
  }

  function displayCategory (xmldoc)
  {

    Questionnodes = xmldoc.getElementsByTagName("Question");
    Answernodes = xmldoc.getElementsByTagName("Answer");
    var i = Math.floor((Math.random()*1000)%Questionnodes.length);
    var i = Math.floor((Math.random()*1000)%Answernodes.length);        

    var displayText1 =
      Questionnodes[i].firstChild.nodeValue;

    var target = document.getElementById("targetDiv1");
    target.innerHTML=displayText1;        


    var displayText2 =
      Answernodes[i].firstChild.nodeValue;

    var target = document.getElementById("targetDiv2");
    target.innerHTML=displayText2;

  }

</script>

Right now, I do not know if I am able to alter this code to get the function I want. I have tried parsing an XML file into a javascript array (and then randomly select and remove an element) but have gotten nowhere atm. If anyone has a few suggestions, I would be most grateful. Once again, I want a function that can randomly select a question & answer element from an XML file, but only show it to the user ONCE. Cheers guys. (sorry this was so long-winded).

write a class with a var hasbeenshown, hasbeenanswered, useranswer, function getquestion, function getanswer.

the instanciated classes, filled with values from your xml file on load you can add to an array and use your random number to choose a random question.

here is a link to an example of how I would do what you're trying to : http://jsfiddle.net/dievardump/xL5mg/4/

I commented some parts of the code and I 'simulate' your getCategory method.

Note : From my code, I think what didn't manage to do is the 'pickRandom' method. I think you have almost all you need to do other parts.

What I do in my code :

  • I have a collection of Question and Answers
  • I have a QuestionAndAnswer constructor

When the server result come, I 'parse' the xml file and fill the collection with QuestionAndAnswer objects.

In the HTML is a 'load a question' button. When you click on it, it call the displayQuestion method.

This method picks (get and remove from) a random QandA object from the collection, then display the question and a button to see the associated answer.

Like i said in the comments, i decided to add question the one after the other, but you can change that by having only one question and response handler and modify its content.

Here is the code if one day jsfiddle decide to not work anymore :

Javascript

(function() {   
// Question and Answer collection
var oQandACollection = {
    collection : [],
    length : 0,

    // get a QandA object
    get : function(i) {
        if (i < this.length) {
            return this.collection[i];
        }      
        return null;
    },

    // add a QandA object
    add : function(qanda) {
         this.collection.push(qanda);
         this.length++;
    },

    // remove a QandA object
    remove : function(i) {
        if (typeof this.collection[i] !== 'undefined') {
            this.collection.splice(i, 1);
            this.length--;
        }
    },

    // randomly pick an object from the collection
    pickRandom : function() {
        if (this.length === 0) return null; // return null if there is no object in the collection
        var i = Math.floor(Math.random() * this.length);
        var qanda = this.get(i);
        this.remove(i);
        return qanda;
    }

};

// Question and Answer Object
var QandA = function(xmlNode) {

    var question = xmlNode.getElementsByTagName('Question')[0] || null;
    var answer = xmlNode.getElementsByTagName('Answer')[0] || null;
    if (question && answer) {
        this.question = question.textContent;
        this.answer = answer.textContent;
    } else {
        return null;   
    }  
};

// function to use as ajax request handler
function fillQandA(xmlDoc) {
    // get all WordQuestions elements
    var wrappers = xmlDoc.getElementsByTagName('WordQuestions');
    for(var i = 0, l = wrappers.length, qanda = null; i < l; i++) {
        // create a new question from the current wrapper
        // we could have perfom the getElementsByTagName('Question') here
        // but since the code is really specific to your example i putted it in the constructor of QandA
        // You can change it
        qanda = new QandA(wrappers[i]);
        if (qanda) {
            oQandACollection.add(qanda);  
        }
    }
};


var eList = document.getElementById('qa-list'),
    eLoadQuestion = document.getElementById('load-qanda');

// functions to display a question
// i choosed to add question the one after the others,
// so i re-create html elements at every display
// but you also can modify it to have just one question at a time
// matter of choice
function displayQuestion() {
    var qanda = oQandACollection.pickRandom(); // get a question

    if (qanda) { // if there is a question

        // create elements
        var eQuestion = document.createElement('p'),
            eAnswer = document.createElement('p'),
            eBtn = document.createElement('button');

        eQuestion.textContent = qanda.question;
        eAnswer.textContent = qanda.answer;

        eQuestion.classNAme += ' question';
        eAnswer.className += ' answer';
        eBtn.textContent = 'Show Answer';


        // add click event listener to the button to show the answer
        eBtn.addEventListener('click', function() {
            eAnswer.style.display = 'block';
            eList.removeChild(eBtn);
        }, false);

        eList.appendChild(eQuestion);
        eList.appendChild(eAnswer);
        eList.appendChild(eBtn);
    }
};

// add click event handler on display
eLoadQuestion.addEventListener('click', displayQuestion, false);



// simulate xhr request
function getCategory() {
    // fill fake Q&A xml document
    var xmlDoc = document.createElement('root');
    for(var i = 0, wrapper = null, question = null, answer = null; i < 10; i++) {
        wrapper = document.createElement('WordQuestions');                   
        question = document.createElement('Question');
        question.textContent = 'Question ' + (i+1);                  
        answer = document.createElement('Answer');
        answer.textContent = 'Answer ' + (i+1);

        wrapper.appendChild(question);
        wrapper.appendChild(answer);

        xmlDoc.appendChild(wrapper);

    }   

    // us as xhr request handler like : fillQandA(XMLHttpRequestObject.responseXML);
    fillQandA(xmlDoc);        
}

getCategory();

// test function
function test() {
    for(var i = oQandACollection.length; i--; ) {
        displayQuestion();
    }
}

//test();
})();

HTML

<div class="wrapper">
<div id="qa-list">
</div>
<button id="load-qanda" value="Load new question">Load new question</button>

</div>

CSS

    .wrapper {
    width : 500px;      
}

.wrapper > div {
    position : relative;
    width : 100%    
}

.answer {
    display : none;    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM