Why value of p is false? [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Here i am try to check if a particular value is exists in the column or not .if exists then I want to add field else I don't want .but p value is false even though the data exists in that particular column .it is showing true for the first time. from the next time onwards it is false.
$('#attach').click((e) => {
e.preventDefault();
var len = $('#tablefd03 tbody tr').length;
debugger;
if (len == 0) {
$("input[id=fd03_Fd03FormFieldSeq]").val(1);
}
else {
var val = prompt("enter the previous order ");
if (!val) return;
else if (isNaN(val)) return alert("Please enter a number !");
else {
var p = false;
$('#tablefd03 tbody tr').each(function (index, el) {
debugger;
if ($(el).children().eq(4).text() == parseInt(val)) {
//s = value;
p = true;
}
else {
p = false;
}
})
if (p) {
$("input[id=fd03_Fd03FormFieldSeq]").val(parseInt(val) + 1);
}
else {
return false;
}
}
}
var form = $('#myform').serialize();
if (!$('#myform').valid()) {
return
}
$.ajax({
url: "/FormDesign/Attach",
method: "POST",
data: form,
})
.done(function (data) {
if (data.isValid) {
//var len=$('#tablefd03 tr').length);
notif({
type: "success",
msg: "Attached successfully",
timeout: 5000,
})
alert("Data Loaded: " + JSON.stringify(data));
//$('#h').replaceWith("#p")
$('#_view-all').html(data.html.fd02partialview);
$('#partialfd03').html(data.html.fd03partialview);
sessionStorage.setItem('user', JSON.stringify(data));
reset();
}
alert("failed")
});
})

As others have said, the problem is with your each loop. If the last row isn't the one you're looking for, then p is going to be false because your code loops through the entire array of rows. What you want to do instead is find the row you're looking for and return as soon as you have it, or return falsey if you don't.
I haven't used jQuery in a long time, so I'll write up an answer for you with regular JavaScript. This is very easy to do with Array.find().
const rowEl = [...document.querySelectorAll('#tablefd03 tbody tr')].find((rowEl) => {
return [...rowEl.querySelectorAll('td')][4]?.textContent === val;
});
In this code, rowEl will contain the row you want, if found. Otherwise rowEl will be undefined.
The .find() method loops through each element of the array until the callback function returns truthy.
We check each row's cell with index 4 (if exists) for textContent and compare against val. If they're equal, this callback will return true, which will cause .find() to stop searching and return the current row. This will be assigned to rowEl.
You didn't provide any HTML to test with, so I'll leave any debugging or implementation to you. Hopefully this gets you started.

Related

weird Error TypeError: Cannot read property 'setValue' of null at onSuccessMapUnitFields [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
This code was running fine until I decided to add 4 more lines of code, so I removed them. But I got this error, funny thing is I added my lines on the Form_onload function. I need help with this.
function Form_OnLoad() {
debugger;
if (Xrm.Page.ui.getFormType() == 1) {
Xrm.Page.getAttribute("quantity").setValue(1);
Xrm.Page.getAttribute("quantity").setSubmitMode("always");
Xrm.Page.getAttribute("isproductoverridden").setValue(true);
Xrm.Page.getAttribute("isproductoverridden").setSubmitMode("always");
}
else {
ActOnFields("disable", "ir_unit");
ActOnFields("show", "salesorderid");
}
}
function Unit_OnChange() {
var Unit = Xrm.Page.getAttribute("ir_unit").getValue();
if (Unit != null && Unit.length > 0) {
var lookupid = Unit[0].id;
var oDataSetName = "ir_unitSet";
var columns = "ir_AmountRate,ir_Expenses,ir_PublishedRate";
var filter = "ir_unitId eq (guid'" + lookupid + "')";
retrieveMultiple(oDataSetName, columns, filter, "", onSuccessMapUnitFields);
Xrm.Page.getAttribute("productdescription").setValue(Unit[0].name);
Xrm.Page.getAttribute("productdescription").setSubmitMode("always");
}
else {
Xrm.Page.getAttribute("priceperunit").setValue(null);
Xrm.Page.getAttribute("priceperunit").setSubmitMode("always");
Xrm.Page.getAttribute("baseamount").setValue(null);
Xrm.Page.getAttribute("baseamount").setSubmitMode("always");
}
}
function onSuccessMapUnitFields(data, textStatus, XmlHttpRequest) {
if (data && data.length > 0) {
var price = 0;
//if (data[0].ir_AmountRate != null && data[0].ir_AmountRate.Value != null) {
//price += parseFloat(eval(data[0].ir_AmountRate.Value));
//}
if (data[0].ir_PublishedRate != null) {
price += parseFloat(eval(data[0].ir_PublishedRate));
}
if (data[0].ir_Expenses != null && data[0].ir_Expenses.Value != null) {
price += parseFloat(eval(data[0].ir_Expenses.Value));
}
Xrm.Page.getAttribute("priceperunit").setValue(price);
Xrm.Page.getAttribute("priceperunit").setSubmitMode("always");
Xrm.Page.getAttribute("baseamount").setValue(price);
Xrm.Page.getAttribute("baseamount").setSubmitMode("always");
Xrm.Page.getAttribute("ir_publishedrate").setValue(price);
Xrm.Page.getAttribute("ir_publishedrate").setSubmitMode("always");
}
}
Add debugger; inside Unit_OnChange function & the success callback function onSuccessMapUnitFields, then while debugging you can figure out that which one of the 3 fields among priceperunit, baseamount, ir_publishedrate is throwing this error.
Also verify if you are calling ActOnFields method to hide those 3 fields anywhere else before calling this setValue(price). Because if the control/attribute is not visible in the form - Xrm.Page.getAttribute returns null, then when you are trying to setValue it fails with this error.
Failsafe approach:
if(Xrm.Page.getAttribute("baseamount") != null){
Xrm.Page.getAttribute("baseamount").setValue(price);
Xrm.Page.getAttribute("baseamount").setSubmitMode("always");
}

Calling a function on a function - Jquery

I have coded a javascript file:
$(function() {
return $(".ajax-form").on("ajax:success", function(e, data, status, xhr) {
var model_name;
model_name = $(this).data('model-name');
console.log('ajax form success');
if (model_name === 'contact') {
return $('#modal-alert-contact').modal('show');
} else {
return $('#modal-alert-demo').modal('show');
}
}).bind("ajax:error", function(e, xhr, status, error) {
var elm, messages, model_name;
model_name = $(this).data('model-name');
console.log('ajax form error');
console.log(model_name);
if (model_name === 'contact') {
if (xhr.responseJSON["email"]) {
elm = $('.alert-contact-fields');
messages = [];
$.each(xhr.responseJSON, function(id, error_messages) {
return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
});
elm.find('.messages').html(messages);
return elm.removeClass('hide');
} else {
elm = $('.alert-contact-fields');
return elm.addClass('hide');
}
} else {
if (xhr.responseJSON["company_name"]) {
elm = $('.alert-demo-fields');
messages = [];
$.each(xhr.responseJSON, function(id, error_messages) {
return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
});
elm.find('.messages').html(messages);
return elm.removeClass('hide');
} else {
elm = $('.alert-demo-fields');
return elm.addClass('hide');
}
}
});
});
and I found it out messy, and repeating same codes.
What I'm want to do is this part:
messages = [];
$.each(xhr.responseJSON, function(id, error_messages) {
return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
});
elm.find('.messages').html(messages);
return elm.removeClass('hide');
I want that part to be a function, and after I do that, I will call that function to use it on my function. Is it possible or there's some technique to improve my coding structure?
Thanks!
I think you want something like this:
$(function() {
var myform = $(".ajax-form");
var makeMessages = function(json) {
return $.map(json, function(error_messages, id) {
return ("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " ");
});
};
myform.on('ajax:success', function(e, data, status, xhr) {
var modal_to_show = ($(this).data('model-name') === 'contact') ? '#modal-alert-contact' : '#modal-alet-demo';
return $(modal_to_show).modal('show');
});
myform.on('ajax:error', function(e, xhr, status, error) {
var fields;
if ($(this).data('model-name') === 'contact') {
fields = $('.alert-contact-fields');
if (xhr.responseJSON["email"]) {
return fields.find('messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
}
return fields.addClass('hide');
}
fields = $('.alert-demo-fields');
if (xhr.responseJSON["company_name"]) {
return fields.find('.messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
}
return fields.addClass('hide');
});
});
makeMessages is a function that takes the json object and returns a set of strings; map() is a much better function for that than each(), because it requires no intermediate array to save the values.
The 'success' handler shows the use of the 'ternary operator', also known as a conditional expression. You want to know which modal to show: this is how you pick it, then have one and only one 'show' operation. It's way easier to debug.
For the 'error' handler, each time you set the messages, you just call makeMessages() with your JSON and get back the array of strings you want. Because you had to find the messages field inside the alert-*-fields, I call end() which pops the current jquery context back one search (from the 'find' to the initial $() call) and then call 'show' on it instead.
Since you call 'return' at the end of a chosen successful operation, there is no need at all for 'else' statements. They're noise. Either your code does its thing, or it falls through to the next stage.
You could remove my fields = set operations, since performance-wise each will only be called once, so it's harmless to have that repetition. But this makes explicit which region you're working in.
If you want to get insanely dense about what you're working on, put all the decision-making up top (what to work on, what to show), and make the rest of the code pure machinery, the 'how' part of your code. The 'error' handler becomes this:
myform.on('ajax:error', function(e, xhr, status, error) {
var handler = (($(this).data('model-name') === 'contact') ?
{ 'fieldclass': '.alert-contact-fields', 'objname': 'email' } :
{ 'fieldclass': '.alert-demo-fields', 'objname': 'company_name' });
var fields = $(handler.fieldclass);
if (xhr.responseJSON[handler.objname]) {
return fields.find('.messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
}
return fields.addClass('hide');
});
At which point 'makeMessages()' just becomes a nice, convenient function because it shows (and names! Good names are always important to maintenance) what you're doing with the JSON object.
One (well, two) last alternatives:
myform.on('ajax:error', function(e, xhr, status, error) {
var drawResults = function(fieldclass, objname) {
var fields = $(fieldclass);
if (xhr.responseJSON[objname]) {
return fields.find('messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
}
return fields.addClass('hide');
};
return ($(this).data('model-name') === 'contact' ?
drawResults('.alert-contact-fields', 'email') :
drawResults('.alert-data-fields', 'company_name'));
/* Absolutely minimal alternative, but some people find
* using the apply method obfuscating. */
return drawResults.apply(this, $(this).data('model-name') === 'contact' ?
['.alert-contact-fields', 'email'] :
['.alert-data-fields', 'company_name']);
});
Rather than use fields and decisions up front, this puts all the decision making at the end, and describes what will happen once the decision is made up front. This uses a more familiar syntax of calling a function. It's important to see that drawResults() has access to the xhr object already, so it isn't necessary to pass it in.
One last possible extraction is to turn $(this).data('model-name') === 'contact' into a function, like isDemo(), so that code only happens once and is also well-named.

Display All ().html in Javascript

Sorry for the lack of description in title, it's difficult to explain.
So I have a simple signup page and I made a bunch of functions in my code that check things such as the username length, make sure the passwords match, etc..
The problem is, if there is more than one error in the users input, it only displays one error at the bottom.
HEre is the JSfiddle: http://jsfiddle.net/LCBradley3k/xqcJS/19/
Javascript:
$('#join').on('click', function () {
var correct = true;
$('input[type="text"], input[type="password"]').each(function (indx) {
var $currentField = $(this);
if ($currentField.val() === '') {
$currentField.addClass('empty');
correct = false;
$currentField.one('keydown', function () {
$currentField.removeClass('empty');
});
} else {
$currentField.removeClass('empty');
}
});
function userLength() {
var x = $('input[name="user"]').val();
if (x.length < 6) {
$('#answer').html('Less than six characters.');
$('input[name="user"]').addClass('empty');
return false;
} else {
return true;
}
}
function passwordCheck() {
var x = $('input[name="password"]').val();
var y = $('input[name="passwordcheck"]').val();
if (x === y) {
return true;
} else {
$('#answer').html('Two different passwords');
$('input[name="password"], input[name="passwordcheck"]').addClass('empty');
return false;
}
}
function validateForm() {
var x = $('input[name="email"]').val();
if (x.indexOf('#') !== -1 && x.lastIndexOf(".") !== -1) {
return true;
} else {
$('#answer').html('Not a valid email');
$('input[name="email"]').addClass('empty');
return false;
}
}
if (correct) {
if (userLength()) {
if (passwordCheck()) {
if (validateForm()) {
$('#answer').html('Thank You!');
setTimeout(function () {
$('.inputs').hide("slide", {
direction: "up"
}, 1000);
}, 2000);
}
}
}
} else {
$('#answer').html('Please fill highlighted fields.');
}
});
You can see that all of them edit the #('#answer') div with .html(). But only one is displayed when there is more than one error. Once that error is fixed and the button is pressed, it will then display the next error. I want them all to be displayed in a list.
I created a fiddle that may be of some help. The idea is to create an array with the errors in it like so:
var errors = [];
errors.push("Error 1");
errors.push("Error 2");
As you step through the validation, every time an error is encountered you simply push the error string onto the array. When you get to the end of the validation you need to compile these errors into html like that can be appended to your $('#answer') element. In this case the items are compiled into an unordered list. You can change this to fit your needs.
var content = "<ul>";
for(var a = 0, len = errors.length; a < len; a++) {
content += "<li>" + errors[a] + "</li>";
}
content += "</ul>";
$('#answer').html(content);
The html is built dynamically and stored in the variable content. content is then appended to your html element that displays the errors (in your case answer).
You have 2 issues with doing what you want.
First, you are only continuing your checks if the first one passes, due to your nested if statements.
Second, you are replacing the #answer html with the message, which means even if you do each check, you will only see the results of the last one.
A simple fix would be to un-nest your if statements, and keep a variable that tracks the overall pass state. Secondly, instead of using .html(), use .append(), but make sure to clear out #answer before starting your checks.
correct &= checkFilled();
correct &= userLength();
correct &= passwordCheck();
correct &= validateForm();
if (correct) {
// ...
}
Fiddle: http://jsfiddle.net/jtbowden/9cFKW/
Note: I made your form filled check it's own function to work better with this method.
You can do some more fancy things, like pushing error messages on an array, and then checking the array for errors at the end and appending all of the messages, but this should get you started.

Javascript Array Losing an Element At Random

I have a very strange issue that I am running into. I am using jsTree from JQueryUI on one of my sites, and I have different implementations of it used in different .js files. One of them seems to work, which is very confusing as it uses almost identical code (only the variable names are different) to the implementation that is broken. The problem comes from the contextmenu function. The code I am using is as follows:
$(document).ready(function () {
if(typeof dryerList == 'undefined' || dryerList.length == 0) {
var dryerList = [];
$.ajax({
url:'../TrackingApp/getGrainBins.php?t=234.23423452353',
async: false,
success: function(text) {
try {
dryerList = $.parseJSON(text);
} catch (e) {
alert('ERROR: ' + e);
}
if(dryerList.length == 0) {
alert('ERROR: No fleet data received.')
}
}
});
}
$("#dryerListTree").jstree({
plugins : ['json_data', 'ui', 'themes', 'contextmenu'],
contextmenu: {items: customBinMenu},
json_data : { data: binNodes }
});
$('#dryerListTree').bind("dblclick.jstree", function (event) {
var node = $(event.target).closest("li");
var id = node[0].id;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
centerMap(dryerList[i].y, dryerList[i].x);
break;
}
}
});
});
function customBinMenu(node) {
if ($(node).hasClass("folder")) {
return;
}
var items = {
centerItem: {
label: "Locate",
action: function () {
// Centers map on selected bin
var id = node[0].id;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
centerMap(dryerList[i].y, dryerList[i].x);
break;
}
}
}
},
dashboardItem: {
label: "Dashboard",
action: function () {
// Opens dryer info window over map
var id = node[0].id;
var dryerIndex = -1;
for(i=0; i < dryerList.length; i++) {
if(id == dryerList[i].id) {
dryerIndex = i;
break;
}
}
}
}
};
return items;
}
The strange bit is, the double-click handler works just fine. When I get to the customBinMenu() function, the dryerList array is there, and dryerList[0] contains 4 of the 5 values that it should- but somehow the 'id' element has been dropped from that object. I have been looking at this for quite some time, and I can't figure out how it can drop a single element from the object without losing any other data, especially when identical code is working for a similar list. Any suggestions?
Ok, I read in your question: 'and dryerList[0] contains 4 of the 5 values that it should- but somehow the 'id' element has been dropped from that object'
So by 'element' and 'value' I assume you mean 'attribute': the node's 'id'-attribute to be precise ??
I see in your code: var id = node[0].id;
That should be: var id = node[0].getAttribute("id");
Good luck!
UPDATE 1:
Ok, if (as per your comment) var id = node[0].id; (getting id from node[0]) is ok, then if(id == dryerList[i].id) looks wrong, since you just (re-)defined id to be the value of node[0]'s id.
Actually I would not use 'id' as a var-name (in this case).
So what if you did: var idc = node[0].getAttribute("id");
and then: if(idc === dryerList[i].getAttribute("id"))
UPDATE 5: You still have some errors by the way:
You forgot a semi-colon to close the alert in:
if(dryerList.length == 0) {
alert('ERROR: No fleet data received.')
}
You should use '===' to compare with '0' on line 2 and 14
naturally in real life you would define function customBinMenu(node) before it was used in your document.ready function.
Fixed by swapping code order.
The same goes for this document.ready function where you used var dryerList before it was defined.
Fixed by: var dryerList = dryerList || []; if(dryerList.length === 0){//ajax & json code}
Could you please confirm if this fiddle, which is now valid javascript, represents your intended baseline-code that still results in your problem of the 'id'-attribute being 'undefined' in dryerList's node-collection (since the code you posted contained some simple errors that are fixed in this jsfiddle, excluding the things mentioned in update 1, since you commented that this is not the problem) ?
May I ask (since you start at document.ready), why do you (still) check if dryerList already exists?
May I ask if you could update that corrected fiddle with some demo-data for us to toy around with?

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;
}

Categories