I have been using javascript to run some simple code that uses the leaflet.js library (in this instance, the particular function is mymap.layerPointToLatLng(), here is the documentation ).
I want to use some data of the form [[[x,y]],[[x,y]],...] (the format is particular for how leaflet.js handles polygons and multipolygons, this kind of format is what I have called 'dim=2'). I need to convert it into latitudes and longitudes (hence the previously mentioned function). Because I do this a lot, I wrote a function to do it for me:
/*-Formatting functions*/
function coordconvert(mapvar,array,dim){
var temp1in=[],tempout1=[],temp2out=[];
if(dim===1){
for(i=0;i<array.length;i++){
tempout1[i]=mapvar.layerPointToLatLng(array[i]);
}
return tempout1;
}
else if(dim===2){
for(i=0;i<array.length;i++){
temp1in=array[i];//each polygon
console.log(i);
console.log(temp1in);
console.log(tempout1);
//tempout1=[];//why do I need this line?
for(j=0;j<temp1in.length;j++){
console.log(tempout1);
var checking = mapvar.layerPointToLatLng(temp1in[j]);
tempout1[j]=mapvar.layerPointToLatLng(temp1in[j]);//each vertex of polygon
console.log(j);
console.log(tempout1);
console.log(checking);
}
temp2out[i]=tempout1;//array of polygons
}
return temp2out;
}
else{
console.log("Unable to process coordinate conversion on array");
return
}
}
However, the 'if(dim===2)' section does not appear to be working correctly, hence all of the console.log lines.
In particular, the assignment tempout1[j]=mapvar.layerPointToLatLng(temp1in[j]); only appears to be working if I uncomment the line //tempout1=[];//why do I need this line?.
Using the console.log's, and viewed using Google Chrome, I get the following outputs:
First few iterations of loop
Final iteration of the loop
So as can be seen, The value (an object) of the final iteration is being included in the array of tempout1 before anything has been assigned to it (I have tried removing the 'if(dim===1)' section, and renaming the tempout1 variable, with no luck), and is being hidden by Chrome(?!?!?!); The value is not being over-written during the loop (as can be seen by the comparison of console.log(checking) and console.log(tempout1).
Why do I have to scrub the variable each time before the nested loop runs? And why is the value from the final iteration getting in before anything happens?
Turns out the solution was quite simple - I wasn't declaring the loop variables properly (i.e. for (var i=o;i<array.length;i++), rather than for (i=o;i<array.length;i++)) I'm not sure how this explains the behaviour of the Google Chrome console, but everything seemed much more stable afterwards.
Related
Sorry if this has been asked before, I'm newish to programming so I'm not sure how exactly to define this issue. So I've been trying to code an AppScript extension to find what geographical area a given point lies in. My function names isInsideWrapper successfully identifies whether or not the given point is inside the area. However, when I try to then write a function to search for which area it's in, isInsideWrapper returns false instead of true for the area the point is in. Here's how the Google sheet looks, with the output for areaSeach and isInsideWrapper shown, as well as some of my code:
function areaFinder (polyRange,pt) {
let arr = []
for (let i = 0; i<polyRange.length; i++){
arr.push(isInsideWrapper(polyRange[i],pt))
}
return arr
}
Google Sheet
I've tried mapping the equation, printing the output of isInsideWrapper on just polyRange1, the area where it should be true (that still comes out as false when done through areaFinder). When I print just polyRange1, it's the same exact thing as the input. So I'm really lost as to why it's returning false. If needed, I can post details of the other callback functions.
I'm really stuck on this javascript question!
So I'm making a web page that will be completely animated (so it can be used for display for example in a television). That animation will be configurable by the user (stored in a database).
Right now, I've already made the code to store the configuration and to get the configuration (I do an AJAX call and save the configuration in an array of json objects) and everything is as it should be.
The problem is in the animation in which I go through the array and use setTimeout function to create animations. To iterate through the array I rotate it
(I use array.push(array.shift()) according to the answer here).
The first time the intervalmaster function is used, everything goes according to plan, but when the function is called again I need to rotate the array once more (because of the last animation) and the array just doesn't rotate!
Bellow I've left a portion of the code that I'm using that reproduces the problem I'm getting. I've also added the array jsonanima with some possible values (In reality the array is probably much bigger and with higher values).
I really don't understand what is happening, I've also considered that this could be a problem of the multiple setTimeout functions because I've read somewhere (couldn't find the link, sorry!) that is not really advised to use multiple setTimeout.
If that's the case is there any other way to do this?
Thank you in advance!
EDIT: Thanks to the comment from mplungjan I've realized that if change the console.log(jsonanimate) to console.log(JSON.stringfy(jsonanima)) it outputs the correct values (the json array rotated). This got me even more confused! Why do I need to JSON.stringfy to get the array in the correct order?!
Anyway, can't test this with the full code now as I'm not in the office, tomorrow I'll give more feedback. Thank you mplungjan.
EDIT2: Finally solved my problem! So the thing was the call to the function recursivegroup (recursivegroup(0);), this call was made before I rotated the array, so when restarting the animation the array would still have the incorrect values and every sub-sequential value was wrong.
A special thanks to mplungjan and trincot for the comments that helped me debug this problem.
Bellow I leave the code corrected so anybody with the same problem can check it out.
jsonanima=[{"VD":5,"A":10,"diff":0.25},{"L":7,"IE":8,"diff":0.25}];
function intervalmaster(flag){
function recursivegroup(index)
{
if(index==0)
{
//animateeach(jsonanima,0);
}
setTimeout(function(){
//HERE IT WORKS
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
//animateeach(jsonanima,0);
//removed the if statement, since it was irrelevant as mplungjan noted
recursivegroup(index+1);
},(jsonanima[0]['diff'])*60*1000);
}
//Changed this
//recursivegroup(0);
var mastertime=0;
for(var key in jsonanima)
{
mastertime+=(jsonanima[key]['diff']);
}
console.log(mastertime,flag);
console.log(JSON.stringify(jsonanima));
if(flag==true)
{
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
}
//changed to here
recursivegroup(0);
masterinterval=setTimeout(function(){intervalmaster(true)},mastertime*60*1000);
}
intervalmaster(false);
I have a script on a website that has been coded for IE. I can't edit the original script, so i'm trying to alter it through js and Jquery (by using a Chrome Plugin).
The script uses next line to add a row to an HTML-table, but gives errors in Chrome:
document.all.tbl.rows(i);
after some research I found out this is a function only used in IE. In Chrome an array is used.
So all these lines should be altered to the following:
document.all.tbl.rows[i]
The same problem occurs with rows[i].cells().
I've tried moving the array to rowsData and overwriting rows to a function retrieving the data from rowsData.
document.all.tbl.rowsData = document.all.tbl.rows; // This seems to work
document.all.tbl.rows = function(id) {
console.log('This function is used');
}
After checking with Chrome's devtools, I've found that rowsData does contain a copy of rows, but rows is still an array. When using document.all.tbl.rows() I still get the same error:
Uncaught TypeError: document.all.tbl.rows is not a function
The only other option is replacing the entire function (which is quite long, and not preferred because there's always a probability it can change).
I'm guessing that overriding a browser variable isn't possible.
Is there some way I can make this work?
Quick question that i seem unable to google...
I'm wondering how to keep an array reference through closure. I think.
Im using AngularJS but raw JS has the same behaviour in my trials.
Context: think of a memory game where you match two images. When two selected tiles mismatch, they flip back but only after showing the selected images. So I want to delay the flip.
I have an array that i .filter to a new array.
$scope.selectedTiles = $scope.tiles.filter($scope.filterSelected);
An aside: This new array; does it only contain references or copies of data? MDN says
constructs a new array of all the values for which callback returns a true value.
Not very clear imo. My conclusion is they are references.
Anyways...
This selectedTiles is sent to a closure in order to keep its references. Only it doesnt.
flipSelectedTiles = function (selection){
return function(){
selection.forEach($scope.flipTile);
}
};
function reset(selection){
return function(){
$scope.flipSelectedTiles(selection);
}
}
var resetTiles = reset(filteredTiles);
$timeout($scope.flipSelectedTiles($scope.selectedTiles), $scope.delay);
I need this because I intend to wait a while before executing the flipSelectedTiles.
I also need to clear the selectedTiles immediately in case someone clicks another image.
selectedTiles.splice(0, $scope.selectedTiles.length);
As the timeout fires the array is empty and nothing happens.
How do I keep an array reference through closure?
Edit: here is a fiddle in plain JS http://jsfiddle.net/Tobis/TkjEF/
Edit: added flipSelectedTiles function
You are keeping a reference. The problem is you're emptying the array too early, as you noted yourself. I believe you need a copy instead:
var resetTiles = reset(filteredTiles.slice(0));
$timeout(resetTiles, $scope.delay);
Also note that you weren't passing a function to $timeout, you were invoking flipSelectedTiles immediately (unless flipSelectedTiles returns a function).
Sometimes comparing two strings within arrays fails. Failing occurs occasionally only in looped ifs. Example code below stands for implementing the problem.
searchTable.sort();
for(n=1;n<searchTable.length;n++){
// alert(searchTable[n-1]!=searchTable[n]);
if(searchTable[n-1]!=searchTable[n]){
idx++;
memTable[idx]=searchTable[n];
}
}
Values in the searchTable are strings for sure, and all values are not similar either.
In loop, all values are set in memTable[idx], despite of the similar values in [n-1] and [n]. Activated alert() shows the right comparison result, but if passes all through. Looks like the comparison in if is done by reference, not by value. How is this possible? Is this a bug in the JavaScript interpreter or what?
Action can be corrected by adding valueOf()-methods to both members in comparison expression. I've crashed this failier whithin looped ifs only. Sometimes it takes a long time to figure out why the code won't work.
You seem to have concluded that the problem is related to the actual data in the arrays. I suspect we can't help more specifically without seeing what that data is.
If putting valueOf() in front makes it work, then you can code a check for when the comparison with valueOf() is different than just straight != and output the two values to the debug console or break into the debugger so you can inspect what values are causing the problem. In other words, write code that catches the problem condition and allows you to inspect it.
Looks like you want to remove double values from an Array.
Try using:
var tmpObj = {}, resultArr = [];
for(n=1;n<searchTable.length;n++){
if (searchTable[n] in tmpObj){
continue;
}
tmpObj[searchTable[n]] = true;
}
for (var l in tmpObj){
resultArr.push(l);
}
Note: this will not differentiate between Numbers and Strings (so 1 equals '1')