I have two arrays.
var fruits = [];
var tasks = [];
When I enter a value in the text field it fires a function that pushes the value to an array. It then fires a separate function that stringifies the array and saves it in local storage. ("when" is my alias for document.addeventlistener).
when(toDo, "keypress", function(event){
if (event.key == "Enter" || event.keyCode == 13) {
pushArray();
stringifyArray(fruits);
toDo.value = "";
}
});
// function that adds new task to the array
function pushArray(){
var newtask = new Task(toDo.value, "No note yet");
fruits.push(newtask);
}
// function that stringifies given array and stores it in local storage
function stringifyArray(array){
var makeString = JSON.stringify(array);
var setItem = localStorage.setItem("tasks", makeString);
}
When I loop through the first array and try to display object.Name and .Note in a div it works fine:
when(button, "click", function(event){
demolist.innerHTML = "";
for(i=0; i< fruits.length; i++){
demolist.innerHTML += fruits[i].Name + " " + fruits[i].Note + "<br>";
}
});
But when I fire a function that parses that array, populates the second and tries to loop through it in the same manner I get "undefined undefined" even though I can see that the array contains all the objects I submitted when I check the console.
function parseArray(){
var getArray = localStorage.getItem("tasks");
var parseObj = JSON.parse(getArray);
tasks.push(parseObj);
}
when(button2, "click", function(event){
function parseArray()
demolist2.innerHTML = "";
for(i=0; i< tasks.length; i++){
demolist2.innerHTML += tasks[i].Name + " " + tasks[i].Note + "<br>";
}
});
https://jsfiddle.net/bjxs3LdL/
(NO JQUERY SOLUTIONS PLEASE)
I am new to coding and stackoverflow so forgive the long post.
Fix your parseArray() function by changing
tasks.push(parseObj);
to
tasks = parseObj;
EDIT: Sorry for all the edits, it's hard to wrap my around the control flow. To fix the issue of the first note not getting saved, add a stringifyArray(fruits); call to the end of your submitNote() function.
The parseArray call is wrong, try rewiriting button2 listener like this:
when(button2, "click", function(event){
parseArray();
demolist2.innerHTML = "";
for(i=0; i< tasks.length; i++){
demolist2.innerHTML += tasks[i].Name + " " + tasks[i].Note + "<br>";
}
});
Otherwise, your code needs a redesign, but that's for another opportunity.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm slightly confused about how to use promises. I've read a few things on promises mainly because it seems like I have to use them. I'm working on a small application which is supposed to search through some pdfs using pdfjs, and they use promises. I knocked up something in nodejs, by looking at various examples on the net but I run into a problem.
Let's look at the code first:
require('pdfjs-dist');
var fs = require('fs');
//var searchTerm = "course";
var searchTerm = "designee";
//var searchTerm = "document";
var wordCounter = 0;
var searchResultJSON = [];
//var data = new Uint8Array(fs.readFileSync('testPdf.pdf'));
//var data = new Uint8Array(fs.readFileSync('advanced-javascript.pdf'));
var data = new Uint8Array(fs.readFileSync('iss4.pdf'));
PDFJS.getDocument(data).then(function (pdfDocument) {
console.log('Number of pages: ' + pdfDocument.numPages );
//var div = document.getElementById('viewer');
for(var i = 1; i<=pdfDocument.numPages; i++ ){//loops thru pages
console.log("i is " + (i));
pdfDocument.getPage((i)).then(function(page){//get page(i),
// console.log("page is " + (i));
//console.log("inside getPage()");
page.getTextContent().then( function(textContent){//get content of pdf
//console.log("inside getTextContent()");
//if( null != textContent.items ){
var page_text = "";
var last_block = null;
var lineWithResult = "";
for( var k = 0; k < textContent.items.length; k++ ){
var block = textContent.items[k];
//console.log("word " + textContent.items.length + " k is " + k );
/* if( last_block != null && last_block.str[last_block.str.length-1] != ' '){
if( block.x < last_block.x )
page_text += "\r\n";
else if ( last_block.y != block.y && ( last_block.str.match(/^(\s?[a-zA-Z])$|^(.+\s[a-zA-Z])$/) == null ))
page_text += ' ';
} */
page_text += block.str;
last_block = block;
lineWithResult = searchPdf(block.str);
if(lineWithResult != null){
console.log(lineWithResult + " wordCounter is " + wordCounter);
}
}//end of for(var k...)
//console.log(" page_text " + page_text);
//console.log(searchResultJSON);
//}
});//end of textContent.items
});//end of getPage
}//end of loop
});
function searchPdf(toSearch){//searching pdf for searchTerm
var result = toSearch.toLowerCase().indexOf(searchTerm);
if(result >=0){//if match is found
wordCounter++;
//console.log("toSearch " + toSearch + " result is " + result + " wordCounter " + wordCounter);
constructResult(toSearch, result);//build the result object
return toSearch;
}
else{//if match not found
return null;
}
}
function constructResult(toSearch, result){//construct array of objects containing: search term, search result and index of search term
searchResultJSON.push({
"TextLine":toSearch,
"SearchTerm":searchTerm,
"Result": result,
});
}
The purpose of this code is to:
loop through the pdf's pages
loop through the content
get the pdf text in a variable line by line
search the pdf content with a keyword
if the keyword finds a match, print the match
get the matches in a javascript object
So, it all works OK but you'll notice that from inside the second for loop (where I get the text of the pdf that is) I call a function, searchPdf() which basically performs the search and from within that function I call another function constructResult(...) which is supposed to create the javascript object with the results.
I have some problems printing this object though, because if I print it outside the scope of the for loop, it is empty because the print call (in my case the console.log) executes before the loop has actually copied and analysed (read process and found a match) the text. So, promises see the way to resolve the problem. Thing is, I'm not sure how to code this in such a way that I can chain the promises and print my object after everything has executed. Any idea?
EDIT:
so to clarify, what I need in sequence is this:
1)loop through pdf (I will have to amend the code to loop through a collection of pdfs at some point soon)
2)get each line of text
3)check that there is a match
4)if so, copy the line of text in the javascript object
5)print the javascript object
Try something like this:
function search(doc, s) {
var allPages = [],
i;
for (var i = 1; i <= doc.numPages; i++) {
allPages.push(doc.getPage(i));
}
// Promise.all returns a promise that resolves once
// each promise inside allPages has been resolved
return Promise.all(allPages)
// pages now contains an array of pages, loop over them
// using map, return the promise to get the content for each page
// return it through Promise.all so we can run the next phase
// once the text is resolved for each page
.then(pages => Promise.all(pages.map(p => p.getTextContent())))
// We now have an array of contents for each page, filter based
// on the passed string
.then(content => content.filter(c => c.indexOf(s) > -1));
}
// This is a mock of the pdf API used in your question
var pdfDocument = {
numPages: 3,
getPage: function(i) {
return Promise.resolve({
getTextContent: function() {
return Promise.resolve('Page ' + i);
}
});
}
}
I am dynamically creating a checkbox. Now I want to call a function(lets say Hello world) whenever the checkbox is checked. I used setAttribute to call the function, but I am facing problems while passing parameters. I want the values of i and j to be passed to function.
Following is my code -
function addTable(message) {
var paxArray=new Array();
var mealsArray= new Array();
mealsArray=['Vegeterian Food','Non Vegeterian Food', 'Indian Continental','Chinese'];
paxArray=message.data;
for(var i=0;i<paxArray.length;i++){
var x= document.createElement('tr');
x.innerHTML=paxArray[i];
document.getElementById("Content").appendChild(x);
for(var j=0;j<mealsArray.length;j++){
var row=document.createElement('tr');
var meal=document.createElement('td');
var check_box=document.createElement('td');
var check=document.createElement('input');
check.type="checkbox";
check.id="checkbox"+i+j;
check.setAttribute("onchange","Helloworld(i+j);");
meal.innerHTML=mealsArray[j];
check_box.appendChild(check)
row.appendChild(check_box);
row.appendChild(meal);
document.getElementById("Content").appendChild(row);
}
}
}
function Helloworld(index){
document.getElementById("text").innerHTML=index;
}
Here i+j you are passing are simply characters not variable values.
Try:
say var i = 4; var j=3;
if you want to call Helloworld(43)
check.setAttribute("onchange","Helloworld("+i+j+");");
if you want to call Helloworld(7)
var k=i+j;
check.setAttribute("onchange","Helloworld("+k+");");
You could do like this
check.setAttribute("onchange",`"Helloworld(" + (i + j) + ");"`);
If you don't use (i + j) and put just "Helloworld(" + i + j + ");", you will get concatenation and not sum
Use
function assignFunction(i, j) {
return function() {
Helloworld(i+j);
}
}
check.onchange = assignFunction(i+j);
Hello I can't find out how to delete a specific value from string when clicking on an element with the string value. its for my todo list.
if (window.localStorage.fullName !== undefined) {
alert('Your browser does not support localStorage');
} else {
$(function () {
console.log('localSorage compitability detected. proceeding...');
global vars & functions
var tdli = [];
add list items
$('#tdladd').click(function () {
$('.todolist ul ul').append("<li class='tdli'>" + $('#tdlinput').val() + "</li>");
tdli.push($('#tdlinput').val());
$('#tdlinput').val('');
var array = tdli + "";
localStorage.setItem('tdlis', array);
console.log(array);
$('#todolist').hide().fadeIn('fast');
});
remove list items
$('li').click(function () {
var itemtoRemove = $(this);
tdli.splice($.inArray(itemtoRemove, tdli), 1);
console.log(tdli);
});
$('#clearall').click(function () {
localStorage.clear();
location.reload();
});
load list items
var tdlitems = localStorage.getItem('tdlis');
var array = tdlitems.split(',');
tdli.push(array);
for (var i = 0; i < array.length; i++) {
array[i] + "<br>";
$('.todolist ul ul').append("<li>" + array[i] + "</li>");
};
console.log(array);
});
}
Assuming that tdli is a jQuery wrapped set (which itself is an array-like-object), it will have DOM nodes stored instead of another jQuery objects. That means, just go like
var itemtoRemove = this;
and you should be fine.
After you posted your complete code, we can see you're actually pushing string values into your tdli Array, but you try to .splice() objects respectively DOM nodes, which of course doesn't make any sense at all (comparing apples to oranges).
BACKGROUND
I am creating a dynamic, multiple-choice quiz written in JavaScript as a culmination to this course. I am following the parasitic inheritance pattern outlined in a follow-up post by the author of the course, and am having trouble completing the project.
PROBLEM
If you refer to this JSBIN, you will see that I have created functions to loadQuestion, displayQuestion, getUserAnswer, getCorrectAnswer, and checkAnswer. checkAnswer is where I am stuck. In this function id like to check if the returned value of getUserAnswer is equal to the returned value of getCorrectAnswer on the currently loaded question, and if so, just log a string to the console for now.
Question.prototype.displayQuestion = function(){
var questionToDisplay = '<div class="question">' + this.question + '</div><ul>';
choiceCounter = 0;
var quizDiv = document.getElementById('quiz');
this.choices.forEach(function(eachChoice){
questionToDisplay += '<li><input type="radio" name="choice" value="' + choiceCounter + '">' + eachChoice + '</li>';
choiceCounter++;
});
questionToDisplay += '</ul>';
quizDiv.innerHTML = questionToDisplay;
};
var i = 0;
Question.prototype.loadQuestion = function(){
if(i < allQuestions.length){
var quest = new MultipleChoiceQuestion(allQuestions[i].question, allQuestions[i].choices, allQuestions[i].correctAnswer);
quest.displayQuestion();
i++;
return quest.getCorrectAnswer();
}
};
Question.prototype.getCorrectAnswer = function() {
return this.correctAnswer;
};
Question.prototype.getUserAnswer = function(){
var radio = document.getElementsByName('choice');
for(var i=0; i < radio.length; i++){
if(radio[i].checked){
return radio[i].value;
}
}
};
//Non-functioning code, this is what im trying to figure out.
/*Question.prototype.checkAnswer = function(){
if(Question.prototype.loadQuestion() == Question.prototype.getUserAnswer()){
console.log('it worked!');
} else {
console.log('keep trying!');
}
};*/
//Load the first question
Question.prototype.loadQuestion();
var button = document.getElementById('next');
button.onclick = function(){
//get the user-selected radio input.
Question.prototype.getUserAnswer();
//Question.prototype.checkAnswer();
//load next question
Question.prototype.loadQuestion();
};
I am new to javascript (and programming) and suspect that the problem lies in some misunderstanding of how return values work?
Thank you!
Found the problem.
You're not adding 1 to the value of radio[i]. Remember that this is an array, and so all the indices will be decreased by 1 because we start counting from 0.
Here is your function:
Question.prototype.getUserAnswer = function(){
var radio = document.getElementsByName('choice');
for(var i=0; i < radio.length; i++){
if(radio[i].checked){
return +(radio[i].value) + 1;
}
}
};
I realize now the problem was more with my approach than any one error. I followed and improved upon an example of another student. Here is the repo for the project as it stands. The most important thing I've learned is how to encapsulate the variables I need all functions to have access too. In this case, a variable called currentQuestionIndex that increments and is available to all functions was important to the solution.
I have a problem to manipulate checkbox values. The ‘change’ event on checkboxes returns an object, in my case:
{"val1":"member","val2":"book","val3":"journal","val4":"new_member","val5":"cds"}
The above object needed to be transformed in order the search engine to consume it like:
{ member,book,journal,new_member,cds}
I have done that with the below code block:
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr=[];
for (var i in value) {
arr.push(value[i])
};
var wrd = new Array(arr);
var joinwrd = wrd.join(",");
var filter = '{' + joinwrd + '}';
//console.log(filter);
//Ext.Msg.alert('Output', '{' + joinwrd + '}');
});
The problem is that I want to the “change” event’s output (“var filter” that is producing the: { member,book,journal,new_member,cds}) to use it elsewhere. I tried to make the whole event a variable (var output = “the change event”) but it doesn’t work.
Maybe it is a silly question but I am a newbie and I need a little help.
Thank you in advance,
Tom
Just pass filter to the function that will use it. You'd have to call it from inside the change handler anyway if you wanted something to happen:
formcheckbox.on('change', function(cb, value){
//...
var filter = "{" + arr.join(",") + "}";
useFilter(filter);
});
function useFilter(filter){
// use the `filter` var here
}
You could make filter a global variable and use it where ever you need it.
// global variable for the search filter
var filter = null;
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr = [],
i,
max;
// the order of the keys isn't guaranteed to be the same in a for(... in ...) loop
// if the order matters (as it looks like) better get them one by one by there names
for (i = 0, max = 5; i <= max; i++) {
arr.push(value["val" + i]);
}
// save the value in a global variable
filter = "{" + arr.join(",") + "}";
console.log(filter);
});