Swapping two elements x and y positions - javascript

I am trying to swap two images .x and .y positions. The method I am using fails because I think once I do first swap they point to same positions or something, seems only one moves to new position hope this makes sense.
theSequence[i].onClick = function(e){
firstObject.push(this);
if(firstObject.length == 2){
firstObject[0].x = firstObject[1].x;
firstObject[0].y = firstObject[1].y;
firstObject[1].x = firstObject[0].x;
firstObject[1].y= firstObject[0].y;
}

You have to use temp variable:
if(firstObject.length == 2)
{
tempX = firstObject[0].x;
tempY = firstObject[0].y;
firstObject[0].x = firstObject[1].x;
firstObject[0].y = firstObject[1].y;
firstObject[1].x = tempX;
firstObject[1].y= tempY;
}

There seems to be a problem with your logic.
When you do:
firstObject[0].x = firstObject[1].x;
firstObject[0].y = firstObject[1].y;
Both images will have the same x and y coords. So, when you do:
firstObject[1].x = firstObject[0].x;
firstObject[1].y= firstObject[0].y;
It's redundant. You need to store the x and y of your firstObject[0] in variables before changing them and then assign the value of those variables to firstObject[1].

To avoid temp variable in ECMAscript you can use:
[a, b] = [b, a];
(like in python) or use this hack:
a = -(b = (a += b) - b) + a;
source

Related

Javascript replace/modify the object that a variable points to?

I have a variable pointing to an object and would like to replace that object with another modified one. Is there any Javascript function that can do what my hypothetical "assign" function does in the example console session below?
var x = [[1,2,3], [4,[8,2,[1,4,"Delete Me"],4],6]]
var y = getSubArrayWithString(x) // Equivalent to y = x[1][1][2] in this case
JSON.stringify(y)
>>> "[1,4,"Delete Me"]"
var newY = y.filter(item => item !== "Delete Me")
y.assign(newY) // Equivalent to x[1][1][2] = newY
JSON.stringify(x)
>>> "[[1,2,3],[4,[8,2,[1,4],4],6]]"
If I do y = newY that just reassigns the y variable to point at the newY object, it doesn't modify x.
I know I could modify y in place using splice, but that won't work when I'm applying more complex changes to get newY
Ideally getSubArrayWithString() would return a reference to the parent of the array you are interested in modifying (and maybe even the index you want). Then it's easy:
var x = [[1,2,3], [4,[8,2,[1,4,"Delete Me"],4],6]]
var [y, ind] = [x[1][1], 2] // getSubArrayWithString returns parent and index
y[ind] = y[ind].filter(item => item !== "Delete Me")
console.log(x)
If your really stuck with just the array reference, you can use splice() to alter the array rather than overwrite it. You could even splice() everything and reassign the new values, but this seems pretty inefficient:
var x = [[1,2,3], [4,[8,2,[1,4,"Delete Me"],4],6]]
var y = x[1][1][2]
var newY = y.filter(item => item !== "Delete Me")
y.splice(0,y.length) // sketchy, but works
Object.assign(y, newY)
console.log(x)

Can't get Lotka-Volterra equations to oscillate stable with math.js

I'm trying to implement a simple Lotka-Volterra system in JavaScript, but get different result from what I see in academic papers and slides. This is my equations:
sim2.eval("dxdt(x, y) = (2 * x) - (x * y)");
sim2.eval("dydt(x, y) = (-0.25 * y) + (x * y)");
using coefficients a = 2, b = 1, c = 0.25 and d = 1. Yet, my result looks like this:
when I expected a stable oscillation as seen in these PDF slides:
Could it be the implementation of ndsolve that causes this? Or a machine error in JavaScript due to floating-point arithmetic?
Disregard, the error was simply using a too big evaluation step (dt = 0.1, must be 0.01 at least). The numerical method used is known for this problem.
For serious purposes use a higher order method, the minimum is fixed step classical Runge-Kutta. Then you can also use dt=0.1, it is stable for multiple periods, I tried tfinal=300 without problems. However you will see the step size in the graph as it is visibly piecewise linear. This is much reduced with half the step size, dt=0.05.
function odesolveRK4(f, x0, dt, tmax) {
var n = f.size()[0]; // Number of variables
var x = x0.clone(),xh=[]; // Current values of variables
var dxdt = [], k1=[], k2=[], k3=[], k4=[]; // Temporary variable to hold time-derivatives
var result = []; // Contains entire solution
var nsteps = math.divide(tmax, dt); // Number of time steps
dt2 = math.divide(dt,2);
dt6 = math.divide(dt,6);
for(var i=0; i<nsteps; i++) {
// compute the 4 stages if the classical order-4 Runge-Kutta method
k1 = f.map(function(fj) {return fj.apply(null, x.toArray()); } );
xh = math.add(x, math.multiply(k1, dt2));
k2 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k2, dt2));
k3 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
xh = math.add(x, math.multiply(k3, dt));
k4 = f.map(function(fj) {return fj.apply(null, xh.toArray()); } );
x = math.add(x, math.multiply(math.add(math.add(k1,k4), math.multiply(math.add(k2,k3),2)), dt6))
if( 0==i%50) console.log("%3d %o %o",i,dt,x.toString());
result.push(x.clone());
}
return math.matrix(result);
}
math.import({odesolveRK4:odesolveRK4});

Why doesn't this function detect overlapping circles?

http://jsfiddle.net/goldrunt/SeAGU/52/
Line 49 checks for "false" on isOnCircle function before creating the new object. Function is on line 32. When creating more object, the function is passing when it should not pass.
if (isOnCanvas(location) && !isOnCircle(location)) {
console.log(location, isOnCanvas(location), isOnCircle(location));
create(location);
In fact I can't get the collision detection to register true no matter what values are passed to it
(Math.pow((a.x - i.x), 2) + Math.pow((a.y - i.y), 2) <= Math.pow((a.radius + i.radius), 2))
here I've fixed and given more descriptive variable names so you can see what's going on.
EDIT: I've noticed you don't always feed a circle but sometimes a point as A, which does not have a .radius property resulting in NaN, which also screws up your comparison.
function circleTest(a,b) {
var DistanceX = a.x - b.x;
var DistanceY = a.y - b.y;
var DistanceCenter = Math.sqrt(DistanceX * DistanceX + DistanceY * DistanceY);
var CollisionDistance = b.radius;
if (a.radius) CollisionDistance += a.radius
return DistanceCenter <= CollisionDistance;
}
I also noticed a problem in your function called "isOnCircle" where you are using i (a number) as if it were a circle object, with the above function this can be fixed like:
function isOnCircle(a) {
for (var i = 0; i < circles.length; i++) {
if (circleTest(a, circles[i])) return true;
}
return false;
}
Two problems:
i is the numerical index you are using to iterate through the circles array but you are using it as if it was a circle object; you need to use circles[i] to get the circle at each iteration.
a is a point and does not have a radius (in the code below I've left a.radius in just in-case you pass in a circle rather than a point and have ORed it with 0 so you get a valid number).
Defining some additional variables (for clarity) then you can replace the isOnCircle function with this:
function isOnCircle(a) {
var i=0,l=circles.length,x,y,d,c;
for (; i < l; ++i) {
c = circles[i];
x = a.x-c.x;
y = a.y-c.y;
d = (a.radius||0)+c.radius;
if (x*x+y*y <= d*d) {
return true;
}
}
return false;
}

trouble with comparing strings in javascript

I'm having a weird issue in JS comparing strings. One string is from a user input.
y = data;
document.getElementById("typeThisWord").innerHTML = y;
x = document.getElementById("inputField");
document.getElementById("youTyped").innerHTML = x.value;
first = document.getElementById("youTyped");
second = document.getElementById("typeThisWord");
if(first==second) correct=true;
When the words are the same, it still comes out false. I added in the 'first' and 'second' variables just to see if it would make a difference. Previously I've tried just comparing 'x' to 'y'. I've also tried x.value==y, x==y.value, and x.value==y.value. THe same with 'first' and 'second.' Surprisingly first.value==second.value came out to be true all the time, even when it shouldn't be.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var x, y;
var first, second;
var availV = window.innerHeight - 100;
var availH = window.innerWidth - 100;
var randV, randH;
var correct = new Boolean(); correct=true;
var imageX;
function displayWord() {
if(correct) {
correct=false;
$.ajax({
url: "http://localhost:25578/TypeGood/VisitsSession",
success: function(data) { y = data; },
async: false
});
document.getElementById("typeThisWord").innerHTML = y;
imageX = document.createElement("img");
imageX.src = "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRPRV4XdE7C9sa0pM-FeXcOSQydg7Sh0INg-ZD6FKZ4wjY8WPHa5Q";
imageX.height = 100;
imageX.width = 100;
imageX.style.position = "absolute";
randV = Math.round( Math.random() * availV );
randH = Math.round( Math.random() * availH );
imageX.style.top = randV + "px";
imageX.style.left = randH + "px";
imageX.style.zIndex = "-20";
document.body.appendChild(imageX);
}
x = document.getElementById("inputField");
document.getElementById("youTyped").innerHTML = x.value;
first = document.getElementById("youTyped").innerHTML;
second = document.getElementById("typeThisWord").innerHTML;
if(first==second) {correct=true;}
x.value = "";
}
</script>
getElementById returns a reference to a DOM element, not a string, so you're not comparing strings, you're comparing DOM elements. Since they're different elements, they aren't ==.
At a minimum, your last three lines should be something like:
first = document.getElementById("youTyped").innerHTML;
second = document.getElementById("typeThisWord").innerHTML;
if(first==second) correct=true;
(E.g., using the innerHTML of the elements, which is a string.) Although I think I'd probably keep the values around in variables rather than going back to the DOM for them.
For Example:
y = data; //data is string value "First"
Change this value to new string "first" >> here f is small
y2 = "first"
Now, When both are of same type, its case sensitive.
if(y==y2)
so values are..
First == first
that will be false.
So make sure of data you are passing in inner html. and make sure you are not adding some white space to it..
I hope this may solve problem. :)
comment back if not solved after modifying the code :)
use this instead of (first==second):
if(first===second)
and retrieve value from html like this:
first = document.getElementById("youTyped").innerHTML;

Is there a js library can can generate a color palette from an image?

Something that might do something like
<img class="image" ... />
$(".image").get_colors()
I know there are few websites where you can upload your image and it would generate the color for you but I want something to put on my website
Something like this where you see the colors generated from the screenshot and can search by colors. I tried to check the source code but I could not see any reference to a js library.
I need this feature to work with js if possible.
EDIT:
The image would be on the page already; I just need to generate its color, so I don't want the uploading features.
Thanks.
You might be interested in this related question and my answer to another one.
Getting all the colors from an image is simple, at least in a browser that supports the canvas element - the technique is described here. You end up with a CanvasPixelArray (described here), which is essentially an array like [r,g,b,a,r,g,b,a, ...] where r,g,b,a are bytes indicating the red, green, blue, and alpha values of each pixel.
The hard part is identifying or creating a small selection of representative colors, rather than the 10,000 colors that might be in a 100x100 image. This is a pretty complicated problem, with many solutions (overview here). You can see Javascript implementations of two possible algorithms in the clusterfck library and my port of the Leptonica Modified Median Cut algorithm.
I did write just for fun. It is a jquery plugin, if you don't use it you can read it for some pointers. If there is some error during the call to get_colors a array is set in the return value to hold the errors, it returns an array of objects, these objects are a histogram of a image(one item in the array for every selected element).
(function($, window, document, undefined){
var canvas = document.createElement('canvas');
if (canvas && canvas.getContext){
$.fn.get_colors = function(){
var rv = [];
this.each(function(){
var tagname = this.tagName.toLowerCase();
if ((tagname === 'img') || (tagname === 'canvas') || (tagname === 'video')){
//something bad can happend when drawing the image
try{
var w = this.getAttribute('width');
var h = this.getAttribute('height');
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
var ctxt = canvas.getContext('2d');
if (ctxt){
ctxt.drawImage(this, 0, 0);
var imagedata = ctxt.getImageData(0, 0, w, h);
var data = imagedata.data;
//log('imagedata.width:'+imagedata.width+' imagedata.height:'+imagedata.height+' w:'+w+' h:'+h);
var obj = {};
var color = '';
var r = 0, g = 0, b = 0, a = 0;
var pix = data.length;
for (pix--; pix > 2; pix-=4){
//a = data[pix - 0];
b = data[pix - 1];
g = data[pix - 2];
r = data[pix - 3];
if (r < 16) r = '0' + r.toString(16);
else r = r.toString(16);
if (g < 16) g = '0' + g.toString(16);
else g = g.toString(16);
if (b < 16) b = '0' + b.toString(16);
else b = b.toString(16);
//if (a < 16) a = '0' + r.toString(16);
//else a = a.toString(16);
//color = r + g + b + a;
color = r + g + b;
if (obj[color] > 0) ++obj[color];
else obj[color] = 1;
}
rv.push(obj);
imagedata = data = obj = null;
}
ctxt = null;
} catch(error){
if (!rv.errors){
rv.errors = [];
}
rv.errors.push(error);
}
}
});
return rv;
};
} else{
$.fn.get_colors = function(){
throw new Error('canvas element support required!');
};
}
})(jQuery, this, this.document);
If a document with only one image with 4 pixels(2x2) "#ff0000, #00ff00, #0000ff, #ff0000", if you do $('img').get_colors(); it returns [{"ff0000": 2, "0000ff": 1, "00ff00":1}].
To learn how to use the canvas element you could look at MDN and at the specs in development for details about pixel manipulation.
Edit: commented out a line I was using when debugging.
Have you seen this project on Github?
http://lokeshdhakar.com/projects/color-thief/
It's a javascript solution. (It depends on two additional libraries: jquery, quantize.js).
var colorThief = new ColorThief();
colorThief.getPalette(sourceImage, 8);
getPalette(sourceImage[, colorCount, quality])
Which will return an array, like so: [ [num, num, num], [num, num, num], ... ]

Categories

Resources