Swapping images in Javascript - javascript

finally started with JS and I have a question.
Why doesn't this code work (I have two images with fir and sec Ids in HTML)
function swap() {
let x = document.getElementById("fir").src
let y = document.getElementById("sec").src
let z = x
x = y
y = z
}
But this one does
function swap() {
let x = document.getElementById("fir")
let y = document.getElementById("sec")
let z = x.src
x.src = y.src
y.src = z
}

It's because document.getElementById("fir").src returns the path of the image (string) whereas in the second case you are manipulating the DOM (reference). you can console log or apply break point the output in both cases and check what's happening.

The reason the first one doesn't work is that while you have swapped the elements that your variables point to, you haven't changed the elements themselves. There are a couple of ways of swapping the elements (one of which you already posted and test)
Swap source fields
Swap outerHTML (z = x.outerHTML; x = y.outerHTML; y = z.outerHtML)
Move the actual elements (z = x.nextSibling; y.parentNode.insertBefore(x,y); z.parentNode.insertBefore(y,z);
Example 3 actually is incomplete: You'd also need to handle the case where there's no nextSibling. But hopefully this gives you more perspective of what attempt 1 and 2 are doing as well as how to change and manipulate elements

Related

Demanding multiple coordinates from an undefined amount of elements

Firstly I would like to give you an example, of what exactly I am talking about, and afterwards what I found out/different problems.
I would like to ask for every element, here points (they do share a class) with a diameter of 1 px. To simplify it, I thought of putting it inside an array. The amount of these points is undefined, there may be 2 or 100.
Afterwards i would like to store the x and y coordinates, which I get with the getBoundingClientRect() function, inside a new array. In which I would use every first for x and every second for y.
Now do not confuse this with the position within the array, I would like to know how I can "convert" the element from a query so I can use the getBoundingClientRect() function.
I hope this is all the information needed. I myself researched on here, but I could not find anything that was near my (rather big) demand.
I do not have any code, which I think would be useful.
I have found a solution myself. It is definitely not the smoothest nor the fastest solution, but it works.
for(iAllPoints=0;iAllPoints<(aPoints-1);iAllPoints++)
{
//Creating necesarry variables and asking for the needed data from CSS
var sPointPos = document.querySelector(".startPoint").getBoundingClientRect();
var tarPoints = document.querySelector(".target");
var AOfTarPoints = document.getElementsByClassName("target").length;
var calculatedDistances = [];
//Demanding all coordinates from each target point. Aswel as calculating the distance
if (iAllPoints!=(aPoints-2))
{
for(i = 0;i<AOfTarPoints;i++)
{
tarPoints = document.querySelector(".target");
//Calculating
var SideA = sPointPos.top - tarPoints.getBoundingClientRect().top;
var SideB = sPointPos.left - tarPoints.getBoundingClientRect().left;
var CEPDistance = Math.sqrt(Math.pow(SideA,2)+Math.pow(SideB,2));
calculatedDistances[i] = CEPDistance;
tarPoints.classList.add("inCalculation");
tarPoints.classList.remove("target");
}
minimum = Math.min.apply(Math,calculatedDistances);
var smallestDistance = document.querySelector(".inCalculation");
document.querySelector(".startPoint").classList.add("used");
document.querySelector(".startPoint").classList.remove("startPoint");
smallestDistance.classList.add("startPoint");
smallestDistance.classList.remove("inCalculation");
//Reseting the left unused points for next point
document.querySelector(".inCalculation").classList.add("target");
document.querySelector(".inCalculation").classList.remove("inCalculation");
finalDistance += minimum;
}
else
{
for(i = 0;i<AOfTarPoints;i++)
{
tarPoints = document.querySelector(".target");
//Calculating
var SideA = sPointPos.top - tarPoints.getBoundingClientRect().top;
var SideB = sPointPos.left - tarPoints.getBoundingClientRect().left;
var CEPDistance = Math.sqrt(Math.pow(SideA,2)+Math.pow(SideB,2));
calculatedDistances[i] = CEPDistance;
tarPoints.classList.add("inCalculation");
tarPoints.classList.remove("target");
}
minimum = Math.min.apply(Math,calculatedDistances);
var smallestDistance = document.querySelector(".inCalculation");
document.querySelector(".startPoint").classList.add("used");
document.querySelector(".startPoint").classList.remove("startPoint");
smallestDistance.classList.add("used");
smallestDistance.classList.remove("inCalculation");
finalDistance += minimum;
}
I haven't given every single Variable, but you should be able to understand it either way.

How can I get the particular point in a THREE.Points object to change his position?

I work on a personal project to try out equations to try to simulate the behavior of a galaxy. I have so far managed to place the Points as I wanted, but now I want to take each point individually to change its position.
The goal for now is just to successfully try to apply a Random Vector to each of the points.
I tried:
var direction = new THREE.Vector3(0.00003, 0.000005, 0);
points.position.add(direction);
but this applies to all Points.
Then I tried something like that:
for (let i = 0; i < points.geometry.attributes.position.count; i++) {
points.geometry.attributes.position[i] = Math.random() * 500
}
points.geometry.attributes.position.needsUpdate = true;
But nothing append :( I thing I missed something but I dind't know what
Here the full code on codepen:
Codepen
When you access:
points.geometry.attributes.position[i]
you're not getting the array of the vertex positions. You're getting the BufferAttribute. What you probably want is the array inside the BufferAttribute:
points.geometry.attributes.position.array[i]
However, this is still not the recommended approach. Three.js recommends you use the .getAttribute() method:
// Get the attribute
const posAttribute = points.geometry.getAttribute("position");
// Get the array inside the attribute
const posArray = posAttribute.array;
// Increment by 3 at a time to access XYZ separately
for(let i3 = 0; i3 < posArray.length; i3 += 3) {
posArray[i3 + 0] = xPosition;
posArray[i3 + 1] = yPosition;
posArray[i3 + 2] = zPosition;
}
// Tell the attribute it needs updatin
posAttribute.needsUpdate = true;

Dynamic variable declaration. Is this even the right method?

A little new to JS so be gentle :)
I'm trying to create a program that holds 5000+ boolean values that dynamically change based on other vars.
const chars = "abcdefghijklmnopqrstuvwxyz0";
const charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0"
const maxNum = 48;
const maxTile = 6;
var tile1, tile2, tile3, tile4, tile5, tile6
// test vars
var tile4 = "A27"
var t4a27 = false
// this snippet will be in an interval loop
for (let i = 1; i <= maxTile; ++i) {
for (let n = 0; n < chars.length; ++n) {
for (let j = 1; j <= maxNum; ++j) {
// this obviously doesnt work
var t[i][`${chars[n]}`][j];
// ^ ^ ^
if (tile[i] == `${charsC[n]}${j}`) {
t[i][h][j] = true;
console.log(t4a27)
} else {
t[i][h][j] = false;
}
}
}
}
For clarification a better word than "tile" for the vars could be "sprite" rather because its a point on the sprite.
The basic concept is the tile vars are designed to output their current position as a string value e.g. "A27". Then this loop will take that information and scan each tile subset to be true/false. So if the sprite lower right quadrant is inside "A27" the output would be t4a27 = true
In practice I can do this with just a lot of code (over 20,000 lines) but I figured their has to be an easier way that requires far less code.
This is probably not the right approach for your problem.
If you really need to store this amount of variables, it is probably best to put them in an object like so:
var tiles = {}
var tileName = 'abc'
// Dynamic setting:
tile[tileName] = true
// Dynamic reading:
console.log(tile[tileName])
I am wondering if you really want to store 5000 variables or if there is another way to calculate them at the time you need time, but that requires a bit more knowledge of the problem.
Javascript doesn't have this kind of ability to reflect local variables.
What you can do is attach all those variables to a global object, and proceed with: Object.keys(your_object) and your_object[key_name_here] = ...
I think you should use a 2-dim array for this. Or use a regular array of booleans with the appropriate size and do the index-magic yourself.
As you said, you are running on coordinates. A-27 is the same as row(1)+field(27) -- considering A is 1
If your field is 500x100, you create an Array as such: let gamefield = Array(500*100);
Warning: I have not tested this for syntax errors, but you should get the idea.
let gamefield = Array(500*100);
// optional gamefield.fill(true);
let row = idx => idx * 500;
let posIdx = (r, c) => row(r) + c;
// there is a sprite with a tiles property that returns
// 4 index positions for the sprite's quadrants as [r,c]
let quadrants = sprite.tiles.reportPositions()
// filter the quadrants where the gamefield at r,c is true
// this might also be a good case for some() instead of filter()
let collisions = quadrants.filter(pos => return gamefield[posIdx(...pos)]);
// if there is any of these, you can kill the sprite.
if(collisions.length > 0) sprite.kill();

iterating through and changing nodes in singly linked list

The problem is I don't understand why this code works. It works, but I just can't wrap my mind around it. Here's a function that deletes a node from a singly linked list. I feel like it shouldn't work because it's not actually changing any of the elements in the list, I'm just changing the value of a variable I have set equal to something in the list. In other words, when I create a "runner" variable to iterate through the list, why are the changes I make to "runner" actually changing the list itself. Analogously, if I do
var x = 1
var y = x
y = 2
Obviously, x is still going to equal 1. Why isn't the same true for my Linked List "runner". In the deleteNode function below, why does changing the runner.next value actually change anything in the node or list that exists outside of the function?
function deleteNode(head, position) {
var runner = head
var counter = 0
while (runner) {
if (counter == position - 1) {
runner.next = runner.next.next
return head;
}
runner = runner.next
counter++
}
}
Its because runner is an object, and so the runner variable is a reference to that object.
for example
const x = {a:1}
const y = x;
x.a = 3
console.log(y.a) // this will print 3 also

A basic Javascript For loop

# http://jsfiddle.net/defencedog/rrKYW/
A recent observation has deeply embezzled my knowledge of js. Look at the code below:
var x = "";
function postbody() {
for (i = 0; i < 5; i++) {
x = x + "<sup>" + i + "</sup><br/>";
document.getElementById("posti").innerHTML = x;
}
}​
The above code's output is similar to that of the following & that is the thing vague to me
var x = "";
function postbody() {
for (i = 0; i < 5; i++) {
x = x + "<sup>" + i + "</sup><br/>";
}
document.getElementById("posti").innerHTML = x;
}​
the latter code must giv me a single (to be concise last value of x) output & not the whole iterated output?
Both snippets accomplish the same thing; The first snippet is just less performant as it overwrites the value 5 times as the string is built up instead of writing the final string once.
unrelated: i is an implicit global. use var.
both will cause a same result.
x = x + ...
Sure it does. You add new code to x in each iteration and then set it in the element. setting innerHTML overwrites the entire content of the element.
In the first loop, each iteration will overwrite the html of the element with a little larger html, but the final iteration is the one that overwrites it with the 'complete' value of x.
So the end results are the same, but the first one is quite a bit slower.
The two examples are identical because on the first the innerHTML is being overwritten on each iteration while the value of the variable x is being concatenated with the other strings. By the last iteration, the element's innerHTML will have x's total value.

Categories