Map markers become inaccurate when past accumulation of 10 properties - javascript

I forked an interesting map application with sidebar information for a different purpose.
However, I noticed today that every time I go past 10 parklets from this repository:
http://mick.github.io/jekyllmap/ or (https://github.com/mick/jekyllmap), it starts getting slightly wonky.
I've poked around in mapping.js from assets/js to see where the problem may be coming from.
I can't figure out where it is coming from.
The markers in my application, when past 10 parklets, the markers get stuck, don't change color, or point to the wrong info.
Any advice on how to get this to work for about 26 properties?
Thanks!
ps.to make it clear, the links above are not my github accounts. figured it would be simpler to link to the original account from which i forked from.

mapping.js line 7
var point = parseInt($(this).attr('data-target').substr(1));
or
var point = parseInt($(this).attr('data-target').substring(1));
and not
var point = parseInt($(this).attr('data-target').substr(1,1));
Edit:
Sorry no need to use substring instead of substr. Just delete second parameter.
As said in substr doc : str.substr(start[, length])
If you set the second parameter .substr(1,1)
The string return is from character 1 (the second in the string as the index starts at 0) for a length of 1.
For #1 and #10 or #11 .substr(1,1) returns 1.
If you don't pass the second parameter .substr(1) you get the original string from character string[0] to the end of the string.
For #1 .substr(1) returns 1.
For #100 .substr(1) returns 100.
For #19298298928 .substr(1) returns 19298298928.
And if you're curious difference between substr and substring is here

Related

Why am i getting unexpected behaviour with the number i copied from my logs

I copied the number ‭7549495‬ from my Laravel log file, this is actually part of a message which I send from textlocal (a messaging service). While sending the message it said your message is invalid. So after looking at all possible issues I copied this number and tried to find its length and I saw some unexpected behaviour.
I copied this number in the browser console and tried to write it as a string and find its length it showed length as 9 even though it has only 7 digits then in another variable I took the same number but this time instead of copying it directly I typed the number and this time I got the length as 7 which is correct. (Screenshot is attached.)
I think while copying the number some special character also gets copied but if it is so then why that extra character is not visible
Please explain why this behaviour occurs, Thanks.
Number is: ‭7549495‬
(I copied and pasted this number directly from my logs, you please copy it from here maybe you can recreate that same issue on your end)
Your number has character 0x202D (left-to-right override) at the beginning and 0x202C (pop directional formatting) at the end. Here's how I determined that:
console.log(
[..."‭7549495‬"].map(c => "0x" + c.codePointAt(0).toString(16).padStart(2, "0"))
);

Why doesn't my function correctly replace when using some regex pattern

This is an extension of this SO question
I made a function to see if i can correctly format any number. The answers below work on tools like https://regex101.com and https://regexr.com/, but not within my function(tried in node and browser):
const
const format = (num, regex) => String(num).replace(regex, '$1')
Basically given any whole number, it should not exceed 15 significant digits. Given any decimal, it should not exceed 2 decimal points.
so...
Now
format(0.12345678901234567890, /^\d{1,13}(\.\d{1,2}|\d{0,2})$/)
returns 0.123456789012345678 instead of 0.123456789012345
but
format(0.123456789012345,/^-?(\d*\.?\d{0,2}).*/)
returns number formatted to 2 deimal points as expected.
Let me try to explain what's going on.
For the given input 0.12345678901234567890 and the regex /^\d{1,13}(\.\d{1,2}|\d{0,2})$/, let's go step by step and see what's happening.
^\d{1,13} Does indeed match the start of the string 0
(\. Now you've opened a new group, and it does match .
\d{1,2} It does find the digits 1 and 2
|\d{0,2} So this part is skipped
) So this is the end of your capture group.
$ This indicates the end of the string, but it won't match, because you've still got 345678901234567890 remaining.
Javascript returns the whole string because the match failed in the end.
Let's try removing $ at the end, to become /^\d{1,13}(\.\d{1,2}|\d{0,2})/
You'd get back ".12345678901234567890". This generates a couple of questions.
Why did the preceding 0 get removed?
Because it was not part of your matching group, enclosed with ().
Why did we not get only two decimal places, i.e. .12?
Remember that you're doing a replace. Which means that by default, the original string will be kept in place, only the parts that match will get replaced. Since 345678901234567890 was not part of the match, it was left intact. The only part that matched was 0.12.
Answer to title question: your function doesn't replace, because there's nothing to replace - the regex doesn't match anything in the string. csb's answer explains that in all details.
But that's perhaps not the answer you really need.
Now, it seems like you have an XY problem. You ask why your call to .replace() doesn't work, but .replace() is definitely not a function you should use. Role of .replace() is replacing parts of string, while you actually want to create a different string. Moreover, in the comments you suggest that your formatting is not only for presenting data to user, but you also intend to use it in some further computation. You also mention cryptocurriencies.
Let's cope with these problems one-by-one.
What to do instead of replace?
Well, just produce the string you need instead of replacing something in the string you don't like. There are some edge cases. Instead of writing all-in-one regex, just handle them one-by-one.
The following code is definitely not best possible, but it's main aim is to be simple and show exactly what is going on.
function format(n) {
const max_significant_digits = 15;
const max_precision = 2;
let digits_before_decimal_point;
if (n < 0) {
// Don't count minus sign.
digits_before_decimal_point = n.toFixed(0).length - 1;
} else {
digits_before_decimal_point = n.toFixed(0).length;
}
if (digits_before_decimal_point > max_significant_digits) {
throw new Error('No good representation for this number');
}
const available_significant_digits_for_precision =
Math.max(0, max_significant_digits - digits_before_decimal_point);
const effective_max_precision =
Math.min(max_precision, available_significant_digits_for_precision);
const with_trailing_zeroes = n.toFixed(effective_max_precision);
// I want to keep the string and change just matching part,
// so here .replace() is a proper method to use.
const withouth_trailing_zeroes = with_trailing_zeroes.replace(/\.?0*$/, '');
return withouth_trailing_zeroes;
}
So, you got the number formatted the way you want. What now?
What can you use this string for?
Well, you can display it to the user. And that's mostly it. The value was rounded to (1) represent it in a different base and (2) fit in limited precision, so it's pretty much useless for any computation. And, BTW, why would you convert it to String in the first place, if what you want is a number?
Was the value you are trying to print ever useful in the first place?
Well, that's the most serious question here. Because, you know, floating point numbers are tricky. And they are absolutely abysmal for representing money. So, most likely the number you are trying to format is already a wrong number.
What to use instead?
Fixed-point arithmetic is the most obvious answer. Works most of the time. However, it's pretty tricky in JS, where number may slip into floating-point representation almost any time. So, it's better to use decimal arithmetic library. Optionally, switch to a language that has built-in bignums and decimals, like Python.

Confounded by special CSS case

I was watching this video, it's a short demo for the Brackets IDE. I'm new to web development so I anticipate being confused by the code I see but there was something in there that I really don't get. Around the 8 minute mark the guy brings up the css line .galleryItem:nth-child(4n+1) Saying that it will only affect the first item in each row in a grid because of the :nth-child(4n+1) can some one please explain the syntax of this line and how it can be used.
P.S. For you Bret Victor fans out there, Brackets seems to do some of his stuff.
The idea here is simply that there are probably four items in each row, so using 4n+1 will affect the first item in each row because it is targeting 1st, 5th, 9th, etc. overall.
I think the 4n part can be thought of as a modulo division matcher (matches everywhere that mod 4 = 0) and the +1 simply shifts that 1 to the right. Thus it includes all the multiples of 4, each with 1 added. And since 0 is technically a multiple of 4, the 1st item is included in this list as well.

Counting occurrences of a string in an array (javascript)

I have a code...
var userArray=userIn.match(/(?:[A-Z][a-z]*|\d+|[()])/g);
...that separates the user input of a chemical formula into its components.
For example, entering Cu(NO3)2N3 will yield
Cu , ( , N , O , 3 , ) , 2 , N , 3.
In finding the percentage of each element in the entire weight, I need to count how many times each element is entered.
So in the example above,
Cu : 1 ,
N : 5 ,
O : 6
Any suggestions of how I should go about doing this?
You need to build a parser
There is no simple way around that. You need nesting and memory, a regular expression can't handle that very well (well, a real CS regulular expression can't handle that at all).
First, you get the result regexp you have. This is called Tokenization.
Now, you have to actually parse that.
I suggest the following approach I will give you pseudo code because I think it will be better deductively. If you have any questions about it let me know:
method chemistryExpression(tokens): #Tokens is the result of your regex
Create an empty map called map
While the next token is a letter, consume it (remove it from the tokens)
2.1 Add the letter to the map with occurrence 1 or increment it by one if it's already inside the map
If the next token is (, consume it: # Deal with nesting
3.1 Add the occurrences from parseExpression(tokens) to the map (note, tokens changed)
3.2 Remove the extra ) you've just encountered
num = consume tokens while the next token is a number and convert to int
Multiply the occurances of all tokens in the map by num
Return the map
Implementation suggestion
The map can just be an object.
Adding to the map is checking if the key is there, if it is not, set it to 1, if it is there, increment its value by one.
Multiplying can be done using a for... in loop.
This solution is recursive this means you're using a function which calls itself (chemistryExpression) in this case. This parser is a very basic example of a recursive descent parser and handles nesting well.
Common sense and good practice necessitate two methods
peek - what is the next token in the tokens, this is tokens[0]
next - grab the next token from tokens, this is tokens.unshift()
For each value in userArray, check if there is a next element anf if that next element is a number, if so, add this number to the count of the current element type, else add 1. You can use an object as a map to store a count for each distinct element type :
var map = { }
map[userArray[/*an element*/] = ...
EDIT : if you have numbers longer than a digit, then in a loop while the next is a number, concatenate all numbers into a string and parseInt()

Find numbers at a specific position

I'm trying to find an expression for JavaScript which gives me the two characters at a specific position.
It's always the same call so its may be not too complicated.
I have always a 10 char long number and i want to replace the first two, the two at place 3 and 4 or the two at place 5 and 6 and so on.
So far I've done this:
number.replace(/\d{2}/, index));
this replace my first 2 digits with 2 others digits.
but now I want to include some variables at which position the digits should be replaced, something like:
number.replace(/\d{atposx,atpox+1}/, index));
that means:
01234567891
and I want sometimes to replace 01 with 02 and sometimes 23 with 56.
(or something like this with other numbers).
I hope I pointed out what I want.
This function works fine:
function replaceChars(input, startPos, replacement){
return input.substring(0,startPos) +
replacement +
input.substring(startPos+replacement.length)
}
Usage:
replaceChars("0123456789",2,"55") // output: 0155456789
Live example: http://jsfiddle.net/FnkpT/
Numbers are fairly easily interpreted as strings in JS. So, if you're working with an actual number (i.e. 9876543210) and not a number that's represented by a string (i.e. '987654321'), just turn the number into a string (''.concat(number); ) and don't limit yourself to the constraints of what you can do with just numbers.
Both of the above examples are fine (bah, they beat me to it), but you can even think about it like this:
var numberString = ''.concat(number);
var numberChunks = numberString.match(/(\d{2})/g);
You've now got an array of chunks that you can either walk through, switch through, or whatever other kind of flow you want to follow. When you're done, just say...
numberString = numberChunks.join('');
number = parseInt(numberString, 10);
You've got your number back as a native number (or skip the last part to just get the string back). And, aside from that, if you're doing multiple replacements.. the more replacements you do in the number, the more efficient breaking it up into chunks and dealing with the chunks are. I did a quick test, and running the 'replaceChars' function was faster on a single change, but will be slower than just splitting into an array if you're doing two or more changes to the data.
Hope that makes sense!
You can try this
function replaceAtIndex(str,value,index) {
return str.substr(0,index)+value+str.substr(index+value.length);
}
replaceAtIndex('0123456789','X',3); // returns "012X456789"
replaceAtIndex('0123456789','XY',3); // returns "012XY56789"

Categories

Resources