How to overcome javascript array iteration skipping record/s - javascript

Having a problem, which occurs in Firefox and Safari, but in Chrome it works fine.
This javascript array contains quiz questions, which I display one at at a time. However, sometimes not all records are iterated. I used the console, and it is definitely loading all questions, but still sometimes skips a record (usually only the first one).
EDIT: I have noticed that on quizes this array works for, all questionids are in order, i.e 290,291,293 in the array. But in in an example of one not working, the quiz id's are in this order, 286,285,287,288 and 285 is the one that is skipped, this could be part of the problem.
Here is my Javascript array code, please help me solve this problem.
var currentquestion;
jQuery.ajax({
url:"quizajax.php",
dataType: "json",
data: {
quizidvalue: <?=$thisquizid?>
},
}).done(function(data) {
questions = data;
for(i in data){
console.log(data[i]);
}
});
function nextQuestion (){
for(i in questions) {
if(i<=currentquestion)
continue;
currentquestion = i;
for(y in questions[i]) {
console.log("CurrentA: "+ currentquestion);
console.log("I: " + i);
console.log(questions[i][y].answerid);
}
console.log("CurrentQ: "+ currentquestion);
console.log("I: " + i);
console.log(questions[i]);
questionVariables ();
break;
}
Example code from db,
questionid | quizid | questiontype | qdescription | qfilelocation | noofanswers | answertype
------------+--------+--------------+------------------+------------------------------------+-------------+------------
285 | 55 | text | 6 answer text | null | 6 | text
287 | 55 | text | 4ans text q | null | 4 | text
289 | 55 | text | 2 answers text q | null | 2 | text
286 | 55 | text | 5 answer text q | null | 5 | text
288 | 55 | text | 3 answer text q | null | 3 | text
290 | 55 | image | image q and a | image/55/712013a88298585d415c.jpeg | 4 | image
291 | 55 | video | video q and a | video/55/8efa10195f0c20d1254f.mp4 | 4 | video

The continue statement is causing the loop to skip part of its execution.
Try debugging so see where code logic has the bug.
for(i in questions) {
if(i<=currentquestion) {
console.log('Skipping question: ' + i); // add debugging
continue;
}
...
EDIT: (several comments based on update)
Its best to iterate through arrays using traditional for loops:
for (var i = 0, len = questions.length; i < len; i++) {
But the outer loop isnt event needed
If you initialize var currentquestion = 0; the outer loop can be replaced
function nextQuestion (){
for(y in questions[currentquestion]) {
console.log("CurrentA: "+ currentquestion);
console.log(questions[currentquestion][y].answerid);
}
console.log("CurrentQ: "+ currentquestion);
console.log(questions[currentquestion]);
questionVariables ();
currentquestion++; //update here
}
It looks like your code depends on order, so you can sort
.done(function(data) {
questions = data;
questions.sort(function(q1,q2){
//assuming questionid is the correct property
if (q1.questionid < q2.questionid) {
return -1;
} else if (q1.questionid > q2.questionid) {
return 1;
}
return 0;
});
...
You could have used jquery.getJSON or $.ajax( { success ....})
You should probably reset currentquestion = 0; in your done method.

Related

Restrict Find and Replace function using map() to single column in a 2d array JavaScript

I am working in Google sheets
I have a find and replace function gotten from here. It works great when the array is made from a single column of data
But, in certain instances in which I want to use my function I have all my data sitting in an array which is being passed from prior processing, the data if printed to the page looks like
| Id | Segment |Other Column| etc..
|----|--------------------|------------|
| 1 | AAA AA|AA|CaaL AA |stuff |
| 2 | AAA-AA|AA|CaaL |stuff |
| 3 | AAA, AA|AA|AA |AA |
| 4 | AA |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | CaaL |stuff |
| 9 | AA |stuff |
I only want to replace data in the Segment column
| Id | Segment ||Other Column| etc..
|----|-------------------|------------|
| 1 | AAA AA|zz|CaaL AA |stuff |
| 2 | AAA-AA|zz|Bob |stuff |
| 3 | AAA, AA|zz|zz |AA |
| 4 | zz |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | Bob |stuff |
| 9 | zz |stuff |
As it is the AA in the Other Column (could be in any column, I have no way of knowing) is being replaced which I do not want
Can the findReplace function be restricted to a single column in values updating that only that column in values ?
I have tried getting the column array I want to restrict values to with
function getColumn(matrix, col, startrow){
var column = [];
for(var i=startrow; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
and then attempting to restrict the input to this column
function fr(input) {
const aCOL = getColumn(values,2,0)
return input.aCOL.map(c => c.replace(regex, (x) => map[x]));
AND
return input.map(c => c.aCOL.map(y => y.replace(regex, (x) => map[x])));
}
I get Cannot read property 'map' of undefined
Thanks
function findReplace(values) {
var search_for = ["AA", "Caal"];
var replace_with = ["zz", "yy"];
var map = {};
search_for.forEach(function(item, i) {
map[item] = replace_with[i];
});
//map = { AA: 'zz', Caal: 'yy' };
const regex = new RegExp("(?<![^|])(?:" + search_for.join("|") + ")(?![^|])", "g");
range.setValues(values.map(fr));
function fr(input) {
return input.map(c => c.replace(regex, (x) => map[x]));
}
}
The code you got from your previous question works fine if you just change the range you're retrieving. So instead of creating a function to extract the column into an array, you can just adjust the range.
If the column you want to replace ('Segment') is the second one, then you can do the following changes.
From:
const col = ss.getRange(2, 3, ss.getLastRow()).getValues();
...
ss.getRange(2, 3, ss.getLastRow()).setValues(col.map(fr));
To:
const col = ss.getRange(2, 2, ss.getLastRow()).getValues();
...
ss.getRange(2, 2, ss.getLastRow()).setValues(col.map(fr));

Angular ngModel doesn't update when `ngModelChange` keeps value

I have a text field represented as: field = {text: "", valid: false}, and an input with [(ngModel)]="field.text".
I want to make that field only accept a defined set of characters (for this issue, numbers), and doing (keypress) doesn't work on mobile, so I did: (ngModelChange)="fieldChanged(field)"
The method does the following:
fieldChanged(field) {
console.log(field.text);
field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join("");
console.log(field.text);
}
And it's behaviour is extremely weird.
Legend:
- input: what key was pressed
- before update: first console.log
- after update: second console.log
- output: what I see on screen in the input
| input | before update | after update | output |
|---------|---------------|--------------|--------|
| "" | "" | "" | "" | <- starting position, no event
| "a" | "a" | "" | "a" |
| "a" | "aa" | "" | "aa" |
| "4" | "aa4" | "4" | "4" |
| "a" | "4a" | "4" | "4a" |
| "a" | "4aa" | "4" | "4aa" |
| "4" | "4aa4" | "44" | "44" |
Why does it always update the output when I enter a legal character? It should be working for each event call.
Edit:
Plunker
I think the cause is that modifying the value on ngModelChange breaks change detection, for example if you change the value back to the previous value, because an invalid character was added.
A workaround:
constructor(private cdRef:ChangeDetectorRef) {}
fieldChanged(field) {
console.log(field.text);
field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join("");
console.log(field.text);
var tmp = field.text;
field.text = null; // or some other value that normally won't ever be in `field.text`
this.cdRef.detectChanges();
field.text = tmp;
this.cdRef.detectChanges(); // I guess this 2nd call won't be necessary
}
If anyone having the issues in updating the value, use setTimeout function while updating
// setTimeout function
setTimeout(() => {
field.text = temp;
this.cdRef.detectChanges();
}, 1);

Create Rows from split array data

I have a table which looks like the example i have provided below with this data
Table
T som da pap
------------------------------
A | soma | label | nami |
----------------------------
B | a:b | acha | wen:nda |
-----------------------------
C | d | k | nd:ke |
-----------------------------
Using the data in javascript/jquery i would like to
create a table like this based on count of pap
T som da pap
------------------------------
A | soma | label | nami |
----------------------------
B | a | acha | wen |
-----------------------------
B | b | acha | nda |
-----------------------------
C | d | k | nd |
-----------------------------
C | d | k | ke |
-----------------------------
Suggestions, I have tried but so far the double data i can only put in td instead of tr
Assuming there are always the same number of items in both cells.
$("#tableID tr").each(function() {
var som = $(this).find("td:eq(1)").text();
var som_array = som.split(':');
if (som_array.length > 1) {
var pap_array = $(this).find("td:eq(3)").text().split(':');
$.each(som_array, function(i, som_el) {
var pap_el = pap_array[i];
var new_row = $(this).clone();
new_row.eq(1).text(som_el);
new_row.eq(3).text(pap_el);
$(this).after(new_row);
}
$(this).remove();
}
});
This loops over all the rows in the table, and checks whether the som column contains multiple items. If it does, it split it up, and also splits up the pap column. Then it loops over these values, makes a copy of the original row, and replaces those columns with the elements of the split strings. Finally it removes the original row.

Hide rows in table A that appear in table B

I have Table (Employees) A:
+----+---------+
| ID | NAME |
+----+---------+
| 1 | ROBERT |
| 2 | JAMES |
| 3 | RICHARD |
| 4 | KANYE |
| 5 | DYLAN |
| 6 | JOHN |
| 7 | JEAN |
| 8 | LOKI |
| 9 | ADAM |
+----+---------+
And Table (Employees) B:
+----+---------+
| ID | NAME |
+----+---------+
| 1 | ROBERT |
| 2 | JAMES |
| 3 | RICHARD |
| 4 | KANYE |
| 5 | DYLAN |
+----+---------+
Those people are my "employees". The names from table B are all the employees on my database and the names from table A are all the employees that I've assigned to project n°1.
I would like to HIDE all names in Table B that already appear in Table A because I don't want to re-assign the same employee to project n°1.
How can I resolve this using jQuery?
a clientside check would be:
function compareLists(listA, listB){
var resultList = [];
listA.forEach(function(itemA){
listB.forEach(function(itemB){
if (itemB.name !== itemA.name)resultList.push(itemB);
}
}
return resultList;
}
or at the serverside (database):
select * from table_b where name not in (select name from table_a)
greetings
Normally you should do that on the server side using SQL as already answered. However, since you ask about javascript. This is the way to filter it at client side:
//collect list of names in A
var table = document.getElementById("TableA");
var names = []
for (var i = 0, row; row = table.rows[i]; i++) {
names.push(row.celss[1]);
}
//check names in B
table = document.getElementById("TableB");
for (var i = 0, row; row = table.rows[i]; i++) {
if(jQuery.inArray(row.cells[1], names) !== -1){
//show row
}else{
//hide row
}
}
I dont have that much knowlwdge in Jquery..
But this query increases perfomance in a large DB.
SELECT
FROM TableB
LEFT JOIN TableA ON TableB.name=TableA.name // id will be better than name
WHERE TableB.name IS NULL
Hope this helps

Add autocalculate summation row and column in asp.net Listview

I'm trying to create ListView which contains ASPxTextBox that the user can enter only numeric value. There are many rows and columns of data. I want to add new row and column that calculate total value from each row and column
For example, if I have data like this:
Student Name | Subject1 | Subject2 | Subject3
----------------------------------------------------------
John ----------- | ------- 23 | --------45 | --------37
Smith ---------- | ------- 41 | --------22 | --------11
Linda ---------- | ------- 35 | --------38 | --------23
I want to be like this
Student Name | Subject1 | Subject2 | Subject3 | Total
------------------------------------------------------------------
John ----------- | ------- 23 | --------45 | --------37 | 105
Smith ---------- | ------- 41 | --------22 | --------11 | --74
Linda ---------- | ------- 35 | --------38 | --------23 | --96
------------------------------------------------------------------
Total----------- | --------99 | -------105 | --------71 | 275
The number of columns (Subject) is fixed but the number of rows depends on data in database.
There are 2 main problems here:
1. I want the summation row and column to execute calculation in client side using javascript. So when one of textboxes is lost focus, it will recalculate the summation value in each row and column.
2. I can't access the value from ASPxTextBox using javascript. I tried using:
var test = document.getElementById('<%# Container.FindControl("txt_Subject1").ClientID %>')
var data = test.value;
but it doesn't seem to work.
The following code also cause error:
var test = document.getElementById('<%# Container.FindControl("txt_Subject1").ClientID %>')
var data = test.GetValue();
And when I tried ClientInstanceName, it always return the value of the last row only:
var data = txt_Subject1.GetValue(); //doesn't work?
Also, I don't want to change ASPxTextBox to asp TextBox because I want to use some of its feature.
You could dinamically assign ClientInstanceName values based on row number:
txt_Subject1_1
txt_Subject1_2
...
txt_Subject1_n
Then use javascript to calculate sum:
var sum = 0;
for (var i = 1; i <= rowCount; i++)
{
sum += parseInt(window['txt_Subject1_' + i].GetValue());
}

Categories

Resources