I am new to JavaScript. I don't know why my code does not work. I am creating functions for returning card stacks quantity. The user will input the card stack quantity. Then the card stacks will be remixed with the following rules. But the result does not appear. Can you please help debugging this code..
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Functions</h1>
<p id="demo"></p>
<script>
var reposition = [];
function Reverse(userinput){
var array = new Array(userinput);
var trueform = new Array(userinput);
for(var i=0; i<userinput; i++){
array[i] = i + 1;
trueform[i] = i + 1;
}
while(! (isEqual(trueform,reposition))){
for(var ii=0; ii<userinput; ii++){
reposition[userinput-ii-1] = array[ii];
if((ii+1) != userinput){
swap((ii+1));
}
}
for(var iii=0; iii<reposition.length; iii++){
array[iii] = reposition[iii];
}
count +=1;
}
return count;
}
function swap(n){
var temp = array[n];
for(var iiii=n; iiii<array.length-1; iiii++){
array[iiii] = array[iiii+1];
}
array[array.length-1]= temp;
}
function isEqual(t, r){
for(var iiiii=0; iiiii<t.length; iiiii++){
if(t[iiiii] != r[iiiii]){
return false;
}
}
return true;
}
document.getElementById("demo").innerHTML = Reverse(4);
</script>
</body>
</html>
The first thing I notice is the variable array is not defined. This is because you are trying to use it in separate functions.
this.array instead of var array
The second thing I notice is that in your while loop you are doing count += 1 which is also not defined anywhere in your code.
I recommend starting with a debugger of some sort so you can even find out what errors you are getting. If you're using Chrome, you can open their DevTools with F12. IE and Firefox both also have their own dev tools and I think they both also use F12 as their hotkey.
Here's a link to the instructions for the Chrome DevTools
Otherwise #DavidR2016 is right about some of your variables being undeclared at runtime in the swap and Reverse functions. It's a little hard to read your code as it is pasted in the question, but when I copied to NotePad++ I was able to format and read it a little better. You also do not need to increment the number of i's in your for loops. You can use just one i because they are scoped to the specific loop, and that will also help with readability.
Related
I am learning JS using open sources and I tried to challenge myself by creating a function that will pull only the even numbers from the given array and return it in a new array that will only contain even numbers.
For example: evensOnly([1,2,3,4,5,6,7,8,9,10]) should return only [2,4,6,8,10];
I have implemented below JS function but it is not giving the correct solution, when I run it on the console, it is saying undefined.
Can someone check and see what I did wrong?
function evensOnly(arr){
for (i=0; i<arr.length; i++){
let check = arr[i]%2;
let evensArray;
if (check === 0){
evensArray.push();
return evensArray;
}
}
}
evensOnly([1,2,3,4,5,6,7,8,9,10]);
evensArray should be defined before the loop.
You need to actually
push the value of arr[i] into evensArray.
You also need to return a
value (in this case, evensArray) after the for loop has
completed.
function evensOnly(arr){
let evensArray = [];
for (i=0; i<arr.length; i++){
let check = arr[i]%2;
if (check === 0){
evensArray.push(arr[i]);
}
}
return evensArray;
}
alert(evensOnly([1,2,3,4,5,6,7,8,9,10]));
I am looking for a way to print out a given variable f.ex. the i of a for-loop for each iteration, without it resulting in the entire console being filled with new lines of new values. Is there a console. method for just printing one line, and updating that as we go?
I realise that you could do this by implementing a text-field in your program which you change the with each iteration, but if there is a way of doing this in the console it would be a bit easier (and perhaps quicker? although I am really not sure about that). Thanks in advance.
If there is still confusion about what im asking, what i want is my console to print out:
"i = " i once, and then update the i in that one line, instead of:
i=1
i=2
i=3
1=4
.
.
.
which gets really messy as you go. For the exact example of the i in a for loop, you could get this value from just console.log()'ing the same thing for each iteration, and a number will pop up beside it (in firefox anyway), but i would like to be able to do this with some more useful information.
Option 1: use console.groupCollapsed() and console.groupEnd():
console.groupCollapsed();
for (let i = 0; i < 100; i+= 1) { console.log(`i = ${i}`) }
console.groupEnd();
Option 2: set the values in an array or a string and log the var when the iterations finish:
let valuesToLog = [];
for (let i = 0; i < 100; i+= 1) { valuesToLog.push(`i = ${i}`) }
// see it as an array
console.log(valuesToLog);
// see it as a string, with each value separated by ', '
console.log(valuesToLog.join(', '));
how about JQuery console.clear()?
$(function(){
loop_counter();
});
function loop_counter() {
for (let i = 1; i <= 100; i++){
console.clear();
console.log ("i=", i)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I am creating a simple program that should utilize the bubble sort algorithm to sort a list of numbers in ascending order.
Just for testing purposes I have added the line alert(unsortedNumbers);and as you can see if you run it, the numbers do not change order no matter how many passes the algorithm does.
The program seems to be stuck in an infinite loop, as 'Another pass' is printed to the console repeatedly. As instructed by this line console.log("Another pass");
As with the bubble sort algorithm, once it does not have to swap any terms on a certain pass, we know this is the sorted list, I have created the variable swapped, however it looks like this is always 1. I think this may be caused by the swapArrayElements() function not swapping the terms.
Why is the function not swapping the index of the terms within the array?
(Code does't seem to run properly on SO's code snippet tool, may have to copy into notepad document)
function main(){
var unsortedNumbers =[7,8,13,1,6,9,43,80]; //Declares unsorted numbers array
alert(unsortedNumbers);
var swapped = 0;
var len = unsortedNumbers.length;
function swapArrayElements(index_a, index_b) { //swaps swapArrayElements[i] with swapArrayElements[ii]
var temp = unsortedNumbers[index_a];
unsortedNumbers[index_a] = unsortedNumbers[index_b];
unsortedNumbers[index_b] = temp;
}
function finish(){
alert(unsortedNumbers);
}
function mainBody(){
for(var i =0;i<len;i++){
var ii =(i+1);
if (unsortedNumbers[i]>unsortedNumbers[ii]){
console.log("Swap elements");
swapArrayElements(i,ii);
swapped=1; // Variable 'swapped' used to check whether or not a swap has been made in each pass
}
if (ii = len){
if (swapped = 1){ // if a swap has been made, runs the main body again
console.log("Another pass");
alert(unsortedNumbers); //Added for debugging
swapped=0;
mainBody();
}else{
console.log("Finish");
finish();
}
}
}
}
mainBody();
}
<head>
</head>
<body onload="main()">
</body>
You have an error in your code:
if (ii = len) {
and also
if (swapped = 1){
it should be double equal
Invalid condition check causing infinite loop:
if (ii = len) & if (swapped = 1) should have == or === operator. This is causing infinity loop.
NOTE: Your code is not appropriate as per the best practices to avoid global variables. You should not use global variables and try
passing variables and returning them back after processing.
Refer this for avoiding globals.
Okay, I hope you don't all facepalm when you see this - I'm still finding my way around javascript.
I am putting together an RSVP form for a wedding website.
I want the guests to be able to add their names to the RSVP form, but only have as many fields showing as required. To this end, after each name field, there is a link to click, which will, when clicked, show a name field for the next guest.
The code below works... but I am sure it can be tidier.
I have tried to insert a for() loop into the code in several different ways, I can see that the for() loop increments correctly to the last value - but when it does so, it leaves only the last addEventListener in place. I can only assume, that I should be using a different kind of loop - or a different approach entirely.
How should I tidy up the following?
<script>
function showNextGuest(i) {
document.getElementsByTagName(\'fieldset\')[i].style.display = \'block\';
}
function initiateShowNextGuest() {
document.getElementsByTagName('fieldset')[0].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(1);},false);
document.getElementsByTagName('fieldset')[1].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(2);},false);
document.getElementsByTagName('fieldset')[2].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(3);},false);
document.getElementsByTagName('fieldset')[3].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(4);},false);
document.getElementsByTagName('fieldset')[4].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(5);},false);
}
window.onload = initiateShowNextGuest();
</script>
Your intuition is right - a for loop could indeed simplify it and so could a query selector:
var fieldsSet = document.querySelectorAll("fieldset"); // get all the field sets
var fieldss = [].slice.call(asSet); // convert the html selection to a JS array.
fields.map(function(field){
return field.querySelector("a"); // get the first link for the field
}).forEach(function(link, i){
// bind the event with the right index.
link.addEventListener("click", showNextGuest.bind(null, i+1), false);
});
This can be shortened to:
var links = document.querySelectorAll("fieldset a:first-of-type");
[].forEach.call(links, function(link, i){
link.addEventListener("click", showNextGuest.bind(null, i+1), false);
});
function nextGuest () {
for(var i = 0; i < 5; i++){
document.getElementsByTagName('fieldset')[i]
.getElementsByTagName('a')[0]
.addEventListener('click',function(){
showNextGuest(parseInt(i + 1));
}, false);
}
}
Benjamin's answer above is the best given, so I have accepted it.
Nevertheless, for the sake of completeness, I wanted to show the (simpler, if less elegant) solution I used in the end, so that future readers can compare and contrast between the code in the question and the code below:
<script>
var initiateShowNextGuest = [];
function showNextGuest(j) {
document.getElementsByTagName('fieldset')[j].style.display = 'block';
}
function initiateShowNextGuestFunction(i) {
return function() {
var j = i + 1;
document.getElementsByTagName('fieldset')[i].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(j);},false);
};
}
function initiateShowNextGuests() {
for (var i = 0; i < 5; i++) {
initiateShowNextGuest[i] = initiateShowNextGuestFunction(i);
initiateShowNextGuest[i]();
}
}
window.onload = initiateShowNextGuests();
</script>
In summary, the function initiateShowNextGuests() loops through (and then executes) initiateShowNextGuestFunction(i) 5 times, setting up the 5 anonymous functions which are manually written out in the code in the original question, while avoiding the closure-loop problem.
Good day!
I'm here to ask help about dynamic variable names in Javascript applied to a constructor. It's been much more difficult than expected. I've read about this issue in numerous forums and webpages but I can't find what I'm doing wrong =/
I'm using a HTML5+Javascript library called EaselJS but my problem it's not related to it but to Javascript syntaxis!
Here's my problem. I got this code:
stage1 = new Stage(document.getElementById("cnvs1"));
stage2 = new Stage(document.getElementById("cnvs2"));
stage3 = new Stage(document.getElementById("cnvs3"));
Here, the variables stage have assigned an Stage object which is initialized with canvas id cnvs This line (in the context of the rest of my code) works!
I'd like to simplify this to a single line with a for like this:
for(i = 0; i < 5; i++){
//Of course this is wrong!
stage[i] = new Stage(document.getElementById("cnvs[i]"));
}
This link here resumes how this can be done: With eval (a lot of people say it's not recommendable) and with window (recommended) Then if I do this (without the for to simplify even more):
var varname = "stage";
var i = 1;
window[varname + i] = new Stage(document.getElementById("cnvs_terminal1"));
The code still works. But I can't figure out how to accomplish a similar solution with the canvas id in quotes. These lines of code fail:
var i = 1;
var varname = "stage";
var varname2 = 'cnvs1';
var varname3 = "\"cnvs1\"";
var varname4 = "\"cnvs1" + i + "\"";
window[varname +i] = new Stage(document.getElementById(window[varname2]));
window[varname +i] = new Stage(document.getElementById(window[varname3]));
window[varname +i] = new Stage(document.getElementById(window[varname4]));
In these attempts even trying to pass the exact value I need (without the i) it's not helping me!! I'm backslashing quotes because I think they are necessary for the getElementbyId=( =( =(
Now I'm clueless! =(
I'm certain there is a way to do this, maybe I don't know the syntax, maybe I don't know how to call variables with reference or by value properly, I don't know...
Please help me, I don't know how to do this simple task!
THANKS A LOT =)
EDIT:
Trying #cHao suggestion I can't do it either! Keeping it simple, I set the for for i to be one only:
for (var i = 1; i <= 1; ++i) {
//I use only one of the following lines at a time of course, but I'll write here my failing tries all together:
stage[i] = new Stage(document.getElementById('cnvs'+i));
stage[i-1] = new Stage(document.getElementById('cnvs'+i));
//Hardcoding the first variable works!
stage1 = new Stage(document.getElementById('cnvs'+i));
}
Half of the problem it's solved, but what to do with the first variable? =/ THANKS!!!!
EDIT 2:
More detail has been requested! Here's a copy/paste example! Just update the EaselJS and an image paths for this to work!
<!DOCTYPE HTML>
<html>
<head>
<script src="easeljs-0.4.0-26/lib/easel.js"></script>
<script type="text/javascript">
function init() {
//MY PROBLEM LIES HERE!!
for (var i = 1; i <= 1; ++i) {
//This code WORKS
stage1 = new Stage(document.getElementById('cnvs'+i));
//This code DOES NOT WORKS
//stage[i] = new Stage(document.getElementById('cnvs'+i));
//stage[i-1] = new Stage(document.getElementById('cnvs'+i));
}
var images = "images/itzapic.jpg";
bitmap = new Bitmap(images);
stage1.addChild(bitmap);
stage1.update();
Ticker.addListener(window);
}
function tick() {
stage1.update();
}
</script>
</head>
<body onload="init()">
<canvas id="cnvs1" width="140" height="82">
</body>
</html>
___________________________________________
EDIT 3: SOLVED!
I'll post the final code for reference to someone who want to use EaselJS to render a single image in as many canvases as needed with the same object. For this you'll need the bitmap.clone() method and arrays for the stages. Thanks to #cHao for helping me out ;)
The following code will render the same image in all canvases! Update as necessary ;)
<!DOCTYPE HTML>
<html>
<head>
<script src="easeljs-0.4.0-26/lib/easel.js"></script>
<script type="text/javascript">
stage = [];
function init() {
for (var i = 1; i <= 6; ++i) {
stage[i-1] = new Stage(document.getElementById('cnvs'+i));
}
var images = "images/itzapic.jpg";
bitmap = new Bitmap(images);
stage[0].addChild(bitmap);
for (var i = 1; i <= 5; ++i) {
stage[i].addChild(bitmap.clone());
}
stage[0].update();
Ticker.addListener(window);
}
function tick() {
for (var i = 0; i < stage.length; ++i) {
stage[i].update();
}
}
</script>
</head>
<body onload="init()">
<canvas id="cnvs1" width="140" height="82"></canvas>
<canvas id="cnvs2" width="140" height="82"></canvas>
<canvas id="cnvs3" width="140" height="82"></canvas>
<canvas id="cnvs4" width="140" height="82"></canvas>
<canvas id="cnvs5" width="140" height="82"></canvas>
<canvas id="cnvs6" width="140" height="82"></canvas>
</body>
</html>
Not sure i get the point of eval'ing or pre-figuring variable names and all that. Seems like you could just do like
for (var i = 1; i <= 5; ++i) {
stage[i] = new Stage(document.getElementById('cnvs' + i));
}
window["varname"] won't help unless varname is global, and...eh. You'll want to avoid globals if you can. Either way, you don't need to escape quotes -- you don't need quotes in the name itself at all unless your IDs have quotes in them (which, AFAIK is invalid anyway) or you're eval'ing (which is evil in itself).
If you're looking to put the stages into an array (which seems like a better goal), you'll want your first stage to be stage[0]. In which case, set stage[i-1] instead of stage[i].
And if you're trying to set stage1, stage2, etc...stop. Don't do that. You have a bunch of items, that you're treating alike...that's the kind of thing arrays were meant for. For one thing, notice how much easier it is to work with array elements than similarly-named variables? I wasn't even seeing the issue, because with arrays it's already a non-issue.
As for your code...watch this.
stage = [];
function init() {
for (var i = 1; i <= 1; ++i) {
stage[i-1] = new Stage(document.getElementById('cnvs'+i));
}
var images = "images/itzapic.jpg";
bitmap = new Bitmap(images);
stage[0].addChild(bitmap);
stage[0].update();
Ticker.addListener(window);
}
function tick() {
for (var i = 0; i < stage.length; ++i) {
stage[i].update();
}
}
Once we switch from the stage1 stage2 brokenness to using an array, now we can have as many stages as we want.
I think you want this:
var stagePrefix = 'stage';
var canvasPrefix = 'cnvs';
//adjust loop below based on your naming e.g. do they start at 0 or 1?
for(var i=1;i<5;i++){
window[stagePrefix + i] = new Stage(document.getElementById(canvasPrefix + i));
}
Rather than using an id with a numeric suffix to reference your canvases, I'd get them by tag name:
var canvases = document.getElementsByTagName("canvas");
Or, if you only want to process a certain set of the canvas elements on the page, give them a class:
var canvases = document.getElementsByClassName("cnvs");
Then, to get an Array of stages from your canvases, hijack the Array.map()* method:
var stages = [].map.call(canvases, function(canvas) {
return new Stage(canvas);
});
*Array.map() is new to JS5, but if your browser supports <canvas> it supports JS5. Regardless, here's the link to an implementation of Array.map() you can use to support older browsers, in case you do have to support older browsers and you aren't already using a JS5 shim.