Why does jquery remove brackets from data html5 attribute? - javascript

I am trying to get the content of a data attribute with jquery but returned data is not what I had set.
With this simple example:
<div id="test" data-test="[1]"></div>
But $('#test').data('test') returns 1 instead of [1]
No problem using pure javascript.
View it online: https://jsfiddle.net/jojhm2nd/

jQuery's data is not an attribute accessor function. (This is a common mistake, easily made.) To just access the attribute, use attr.
$("#test").attr("data-test");
data does read data-* attributes, but only to initialize jQuery's data cache for that element. (And it never writes attributes.) It does a whole series of things including changing names (data-testing-one-two-three becomes testingOneTwoThree, for instance) and interpreting the values. In this case, it interprets the value as an array because it starts with [. When you show that array with alert, it's coerced to a string, and when you coerce an array to a string, that does an Array#join. If your attribute had been [1, 2], for instance, you'd've seen 1,2 as the result.
From the docs linked above:
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.
When the data attribute is an object (starts with '{') or array (starts with '[') then jQuery.parseJSON is used to parse the string; it must follow valid JSON syntax including quoted property names. If the value isn't parseable as a JavaScript value, it is left as a string.

jQuery does magic when you use the .data method.
From the jQuery website:
Every attempt is made to convert the string to a JavaScript value
(this includes booleans, numbers, objects, arrays, and null).
You can use the .attr method and do:
$('#test').attr('data-test');

Related

JavaScript code to evaluate string arithmetic expression containing multiple arrays

I want to pass an arithmetic expression as a string to Javascript and this string can contain any number of numerical arrays which will be dynamically populated.
For Eg: I need to evaluate the below expression
(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024 , Where both pmPdcpVolDlDrb and pmPdcpVolDlSrb are numeric arrays
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
This expression can change and the number of variables involved can also change. I need a generalized way of handling it. I wrote the below code and it serves my purpose. I need to know if there is a better and standard way for the same.
// Expression for evaluation where pmPdcpVolDlDrb and pmPdcpVolDlSrb are arrays
expression="(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024"
// Seperating out the variables from the expression. In my case variable names always start with pm
variables=expression.split(/\W+/).filter(word => word.includes("pm"));
array=[]
for(i=0;i<variables.length;i++){
array[i]= [1,2,3,4]// Replace with actual code to get the values of arrays to be computed
if (i===0)
expression=expression.replace(variables[i],"a")
else
expression=expression.replace(variables[i],"array["+i+"][i]")
}
resultantArray=array[0].map((a, i) => eval(expression))

alternative to JSON.parse() for maintaining decimal precision?

I'm calling JSON.parse() to parse a JSON string which has small decimals.
The precision of the decimals is not being maintained after parsing. For example, a value like 3.1e-7 is being returned instead of the actual decimal.
How can I deserialize a JSON string in ng2+ while maintaining decimal precision?
UPDATE
I was thinking about mapping out the values from the string and then setting the values manually to the object after JSON.parse() but when I set a different small decimal number as a property value, the same number formatting occurs. So is this problem not necessarily unique to JSON.parse() but to Javascript in general? Or does JSON.parse() somehow configure property types in a fixed way?
As soon as you pass your JSON string through JSON.parse, you'll lose precision because of the way floating point math works. You'll need to store the number as an object designed for storing arbitrary-precision numbers, and you'll need to fiddle with the string itself before parsing it. The simplest way is with regexes. JSON is a context free grammar, and regexes work on regular grammars, so the warning applies:
WARNING: PARSING CFG WITH REGEX MAY SUMMON ZALGO
This regex should turn the numbers in your JSON into strings:
let stringedJSON = origJSON.replace(/:\s*([-+Ee0-9.]+)/g, ': "uniqueprefix$1"');
But I haven't tested it extensively and it definitely will screw things up if you have keys that are something like data:42.
Assuming it worked correctly, stringedJSON should now be something like {"foo": "uniqueprefix0.00000017", "bar": "an actual string"}. You can parse this with JSON.parse without losing precision, but uniqueprefix0.00000017 isn't what you want. JSON.parse can be called with an extra reviver argument, which transforms values passed to it before returning them. You can use this to convert your data back into a useful form:
let o = JSON.parse(stringedJSON, (key, value) => {
// only changing strings
if (typeof value !== 'string') return value;
// only changing number strings
if (!value.startsWith('uniqueprefix')) return value;
// chop off the prefix
value = value.slice('uniqueprefix'.length);
// pick your favorite arbitrary-precision library
return new Big(value);
});

Can JSON values be numbers?

Can JSON values (not keys) be numbers, or do they HAVE to be strings only? So the following is valid.
{"number":"6"}
But is the following also valid?
{"number":6}
In JSON, 6 is the number six. "6" is a string containing the digit 6. So the answer to the question "Can json numbers be quoted?" is basically "no," because if you put them in quotes, they're not numbers anymore.
The only thing that needs to be between quotes is the property name (number).
It is valid JSON syntax. But beware that different programming languages will parse JSON differently..
https://www.freeformatter.com/json-validator.html
Json values can be
a string
a number
an object (JSON object)
an array
a boolean
null
See - https://www.w3schools.com/js/js_json_datatypes.asp

How does object[[["key"]]] evaluate to object["key"] in javascript? [duplicate]

This question already has answers here:
Why does accessing an element in an object using an array as a key work?
(3 answers)
Closed 6 years ago.
Why does javascript evaluate the following as true, given that object foo has a valid property bar?
foo[[[["bar"]]]] === foo["bar"]
Based on operator precedence, I would think foo[[[["bar"]]]] is trying to access a property with the array [[["bar"]]] as the key, but why does that still "flatten down" to the same as foo["bar"]?
Colleagues of mine are saying javascript parsers have bracket simplifying which ignores the extra brackets. I don't think this is true since saving [[["foo"]]] to a variable test gives the same result:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
What aspect of the language or parser is causing this behavior? Thanks!
JavaScript bracket notation accepts an expression, but it always converts the value of that expression to a string. Thus if you pass in an array, it will attempt to convert it to a string. In your case you are passing in an array [[["bar"]]], and [[["bar"]]].toString() === "bar".
If you are wondering why [[["bar"]]].toString() === "bar", it is because when an array arr is converted to a string implicitly it is like calling arr.join(','). That is each of its elements are converted to strings and then joined in a comma separated string. When the array only has one element, the string representation of the array is just the string representation of that one element. In your case your array ([[["bar"]]]) has one element: [["bar"]].
That array is converted to a string too, and since it is also a one element array, the string representation of it is the string representation of that single element: ["bar"].
["bar"] is also an array with one element, which is a string, so the string representation of ["bar"] is just "bar".
What this comes down to is: [[["bar"]]].toString() === "bar"
and foo[[[["bar"]]]] is the same as foo[[[["bar"]]].toString()].
You would also find that:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2".
Let's see how foo[[[["bar"]]]] is evaluated, step-by step:
The outermost brackets in foo[...] denote a property
accessor. The expression foo[[[["bar"]]]] thus translates to
accessing a property of foo with name [[["bar"]]].
According to the ECMA standard, the abstract operation
ToPropertyKey(name) is then used to turn the name [[["bar"]]]
into a property key value:
A property key value is either an ECMAScript String value or a Symbol
value.
The name [[["bar"]]] is not of type Symbol and thus converted
into a string. An array is converted to a string by joining all its
string converted values:
[[["bar"]]].toString() === "bar"
Which finally means that our property key actually becomes "bar":
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]

Step through JSON Object, Use Regex to create Javascript Date Objects from Unix Timestamp for Google Chart

I've generated the following JSON Object in php and am passing it through AJAX to my javascript. This JSON object as is will not suffice since the Google Charts API I am using needs a javascript date object for each date in the JSON.
My dates are currently encoded in UNIX timestamp -- 1199170800,1201849200,1343800800,1346479200. I figure I could add a regex quantifier on one side of the timestamp (ie: ~1346479200), use REGEX to find the date based on the quantifier, convert the date to javascript object, and then replace each quantifier with the regex. Easier said then done for some.
{"cols":[{"type":"date","label":"FromDate"},{"type":"number","label":"Electricity Use
(KWH)"},{"type":"number","label":"Cooling Degree Days"}],"rows":[{"c":
[{"v":1199170800,"f":"Jan-08"},{"v":"559280","f":"559,280"},{"v":"0"}]},{"c":
[{"v":1201849200,"f":"Feb-08"},{"v":"653193","f":"653,193"},{"v":"381"}]},{"c":
[{"v":1343800800,"f":"Aug-12"},{"v":"667874","f":"667,874"},{"v":"322"}]},{"c":
[{"v":1346479200,"f":"Sep-12"},{"v":"687299","f":"687,299"},{"v":"101"}]}]}
I've looked through many similar posts to get some ideas, but I can't solve this one... Similar, seemingly useful posts:
Loop through object get value using regex key matches Javascript
http://sudarshanbhalerao.wordpress.com/2011/08/14/convert-json-date-into-javascript-date/
Date Range Google Chart Tools
No regular expressions needed.
Parse the JSON into a JavaScript object.
Loop through the "rows" key of the resulting object.
For each item, get the "c" key, which looks like it's the value you need.
In the above example, the values are strings, so you should convert them to integers using parseInt.
Create a new Date object with each one, and pass it the integer value, multiplied by 1000. If you do new Date(integer), it will create an object using that timestamp, but the value is expected to be in milliseconds, not seconds like a normal UNIX timestamp.

Categories

Resources