Data-attribute retrieval and parsing javascript - javascript

I am new to javascript programming and i am stuck with data-attribute retrieval.
The below link is a bit useful for people using jQuery
store and retrieve javascript arrays into and from HTML5 data attributes
I would like to do the same with vanilla js. With the help of custom data-attributes i would like to create objects & array.
<div id="getAnimation"
data-r="564"
data-c="96"
data-custom="x:0;y:0;z:0;rotationX:0;rotationY:0;rotationZ:0;scaleX:0.75;scaleY:0.75; skewX:0;skewY:0;opacity:0;transformPerspective:600;transformOrigin:50% 50%;"
data-s="700"
data-st="1400"
</div>
Do HTML5 custom data attributes “work” in IE 6?
The above link helps in getting data attributes very well but how can be filter the string in data-custom or straight create an object of data-custom.
If someone know a library to do this please let me know

Here are a couple quick functions which will let you store, retrieve and delete any JSON-able data to a data attribute
function setData(node, data_name, data_value) {
node.dataset[data_name] = JSON.stringify(data_value);
}
function getData(node, data_name) {
return JSON.parse(node.dataset[data_name]);
}
function delData(node, data_name) {
return delete node.dataset[data_name];
}
Then to write an Array to #getAnimation in data-fizz
// variables to use
var elm = document.getElementById('getAnimation'),
foo = [1, 2, 3, 'a', 'b', 'c'];
// store it
setData(elm, 'fizz', foo);
// retrieve it
var bar = getData(elm, 'fizz');
// look what we have
console.log(bar); // [1, 2, 3, "a", "b", "c"]
Requires IE 11+ because I use node.dataset, if you change this to the methods node.setAttribute, node.getAttribute and node.removeAttribute as used, the requirement drops to IE 8+ because of the JSON.stringify and JSON.parse

That particular example is quite straight forward: It's a series of name:value pairs separated with semicolons. So you can get an array of the pairs using split, and then get the name and valid separate using split again. If you want to create properties on an object using those names and values, you can do that with bracketed notation:
// Get the value
var val = theElement.getAttribute("data-custom");
// Split it into fields on `;` (with optional whitespace on either side)
var fields = val.split(/\s*;\s*/);
// Create a blank object
var obj = {};
// Loop through the fields, creating object properties:
fields.forEach(function(field) {
// Split the field on :, again with optional whitespace either side
var parts = field.split(/\s*:\s*/);
// Create a property on the object using the name, and assigning the value
obj[parts[0]] = parts[1];
});
I'm using String#split there, giving it a regular expression to tell it where the split up the string.
In the resulting object, with just the code above, the property values will all be strings. For instance, obj.scaleX will be the string "0.75". If you need them as numbers, you can convert them to numbers in any of several ways:
parseFloat, which will convert as many characters as it can but ignore trailing characters. so parseFloat("0.75foo") is 0.75, not an error.
Number, which will not be tolerant like parseFloat, Number("0.75foo") is NaN, not 0.75.
Applying any mathematical operator, the unary + is common: +"0.75" is 0.75.
So rather than just grabbing the values as strings, we could check to see if they look like they might be numbers and convert them if so:
// Loop through the fields, creating object properties:
fields.forEach(function(field) {
// Split the field on :, again with optional whitespace either side
var parts = field.split(/\s*:\s*/);
// Does the value look like a number?
if (/(?:^\d+$)|(?:^\d+\.\d+$)/.test(parts[1])) {
// Yes
obj[parts[0]] = +parts[1];
}
else {
// No
obj[parts[0]] = parts[1];
}
});
That assumes . as the decimal separator, and assumes there won't be a thousands separator.
Side note: Above I've used Array#forEach, which is an ES5 feature not present on older browsers. forEach can be "shimmed" on older browsers, though. You can see all sorts of ways of looping through arrays in this answer here on SO.

Related

Pattern Matching in javascript returning true if first array has 2 and second array has 22 How do i solve this?

I have two arrays one of it is having user id and another one is having user ids. Those arrays are as follows.
1)The array which is having user id.
data[key].effective_employees Which is eaqual to [2].
Now I have another array which is having numbers of employee ids which is as follows.
data2[0].id Which is eaqual to [2,22,21].
And now I am trying to see whether the array two has number in array 1 I am using the following logic to see whether it is working or not.
if ((/^\d+$/.test(_.intersection([data2[0].id.toString()], data[key].effective_employees)))) {
let isElem = _.contains(returnStackFilterd, value);
if (isElem == false) {
returnStackFilterd.push(value);
}
} else {
returnStackFilterd = _.without(returnStackFilterd, value);
}
But this is showing true for the number 2 if the array two is having 22. Psudo code of what is happening with it is as follows.
if([2]is in[22,21]){ it is printing true} I want false here as the number two is not in the second array. The second array contains 22 and 21 which is not eaqual to 2
How do i solve this problem? The above psudo code should print false.
Let's break down your test expression and see why it doesn't work.
First off, we know that data[key].effective_employees is [2]. data2[0].id might be [2, 22, 21] or [22, 21]. If I'm understanding your question correctly, you want the whole test expression to return true in the first case and false in the second case.
Rebuilding your test expression from the bottom up, the innermost expression we find is this:
data2[0].id.toString()
This is a string with the value '2,22,21' or '22,21', depending on which case we are talking about. Next, you wrap this string in an array:
[data2[0].id.toString()]
So now we have ['2,22,21'] or ['22,21']. Note the quotes; in either case, it is an array with a single element that is a string.
Next, you take the intersection of this array with data[key].effective_employees, which we know is [2]:
_.intersection([data2[0].id.toString()], data[key].effective_employees)
So this expression is effectively
_.intersection(['2,22,21'], [2])
or
_.intersection(['22,21'], [2])
You are always taking the intersection of two arrays, where the first contains a single string and the second contains a number. They can't have any elements in common, so that's always going to produce an empty array ([]).
Finally, you test whether that empty array matches a regular expression:
/^\d+$/.test(_.intersection([data2[0].id.toString()], data[key].effective_employees))
// is effectively the same as
/^\d+$/.test([])
Regular expressions are supposed to be matched against a string, not an array. JavaScript is very lenient in situations like these and will coerce the value you're passing to a string. That means that the value [] is first converted to the empty string '' before being matched to the regular expression /^\d+$/. The empty string does not contain any digits, so this test always returns false.
This is why your test doesn't work as intended. However, let's take a few steps back, because you seem to be doing many things you don't need to do. Why convert arrays to strings (and then back to array)? Why match against a regular expression, if you just want to know whether two arrays have elements in common?
The following, simpler expression will give you the elements that data[key].effective_employees and data2[0].id have in common:
_.intersection(data[key].effective_employees, data2[0].id)
This will evaluate to either [2] or [], depending on whether data[key].effective_employees contains the number 2 or not.
I suggest saving the result of this expression to a variable, because it makes your code easier to read. Let's call it commonIds:
const commonIds = _.intersection(data[key].effective_employees, data2[0].id)
Now you can formulate different conditions, based on what exactly you want this intersection to be like. My impression is that you just want it to be nonempty (i.e., at least one element in common). In that case, you can compare its length to zero:
if (commonIds.length > 0) {
// code for when there is an overlap
} else {
// code for when there is no overlap
}
As a final note, I recommend assigning your base expressions data[key].effective_employees and data2[0].id to variables as well. Again, this makes your code more readable, and it also ensures that you need to change only one line of code if those base expressions change. Putting it all together:
const key = 'x';
const data = { [key]: {
effective_employees: [2],
}};
const data2 = [{
id: [2, 22, 21],
}];
const userId = data[key].effective_employees;
const employeeIds = data2[0].id;
const commonIds = _.intersection(userId, employeeIds);
if (commonIds.length > 0) {
console.log('userId appears in employeeIds');
} else {
console.log('userId does not appear in employeeIds');
}
<script src="https://underscorejs.org/underscore-umd-min.js"></script>
If data[key].effective_employees is the number 2, and data2[0].id is the array [2, 22, 21], the expression to test whether data2[0].id contains data[key].effective_employees is:
data2[0].id.includes(data[key].effective_employees)
From your original question, data2[0].id.toString() coerces the array to a string 2,22,21, which is no use to you. You also do not need to use Underscore for this.

How to search array of strings and produce suggestive results

I have an array of Strings in JavaScript. I am trying to develop a function that
Takes a substring as an input.
Searches through the array.
Returns strings from the array close to the substring. The list will be provided as suggestions to the caller.
For example:-
Array contains the below entries.
Hello
What is hello
World
Spacearenotthereinthishello
HELLO
Highway to hell
JavaScript
StackOverflow
I invoke the function as shown below
var result[] = searchFunc('hell');
The result array should contain
Hello
What is hello
Spacearenotthereinthishello
HELLO
Highway to hell
It is possible that the array could contain atleast 100 strings ( or more). I am looking for a scalable solution.
Initially, i figured i should sort and then do a binary search but its cumbersome to do if you wanna pull of all the suggestions from the master array for a particular string input. I am looking for algorithms that can help me achieve a faster search. I am not that worried about insertion timecomplexity in master array.
I did look up multiple stack overflow posts. They do speak about searching a big book for specific strings. None of them talk about returning suggestions from an array for a substring.
Your help is appreciated.
YourArray.filter() will do the job. Quick prototype:
var results = arrayName.filter(function(value) {
return value.toLowerCase().indexOf(searchStr.toLowerCase()) >= 0;
});
Quick Answer (TL;DR)
Use Array.prototype.filter()
Detailed Answer
Context
Javascript
Array filtering
Problem
Scenario: Developer wishes to filter an array for matches on a substring
Solution
// declare array of string fragments
myArrayOfStringFragments = /* TODO: get the content [ ... ] */
// optional step, normalize all strings to lower-case
/* TODO: input normalization with Array.prototype.map() or something similar */
// declare comparison function
function strContainsMatch(slookfor) {
return slookfor.includes("ello");
}
// iterate using Array.prototype.filter()
var filtered = myArrayOfStringFragments.filter(strContainsMatch);
Pitfalls
Data input normalization (are differences based on letter-case significant?)
string comparison based on non-ascii characters
string.includes() method may not be available, instead use string.indexOf()
avoiding false-postive matches based on chosen substring
(e.g., if you are looking for hello then hell will match more than you want, and it will miss Hello if your input is not normalized to lowercase)
See also
How can I only keep items of an array that match a certain condition?
Alternate solution would be to create a regex to do the same.
var condition = new RegExp("hell", 'g');
var results = arrayName.filter(function(value) {
return condition.test(value.toLowerCase())
});

JSON Data format

Not very familiar with JSON data and how to create it using JavaScript.this is what i am trying
i have created two JS variables
var json={};
var json1={};
i have some certain loops to iterate data and loops like
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=JSON.stringify(json);
}
Doing this i am getting following output
Required: "{"Center":"radio_Required_Center_0,radio_Required_Center_1,","Left":"radio_Required_Left_0,"}"
which is not a valid JSON format.My idea id to create a outer-key say Required and than an inner one's in my case Center and Left
so that i can iterate each value with respect to key Center (i can break the string based on ')
i am not sure how to create correct structure and i don't want to do it on server side which can be done easily.
any solution or hint will really be helpful.
Edit
var data= JSON.stringify(json1);
giving following output
{"Required":"{\"Center\":\"radio_Required_Center_0,radio_Required_Center_1,\",\"Left\":\"radio_Required_Left_0,\"}"}
which is valid JSON data, now i need to execute some code based on the data in the JSON and here are my requirements
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
My real challenge is at step number 2 and 3 where i need to fetch the keys and its associated values and those key and not predefined so i can not access them based on there name.
I am thinking of a way to get key and its values without hard coding key names and execute my logic.
is it possible in by this approach or not?
If you're using a modern version of Javascript, it comes with JSON functions built-in.
var jsonString = JSON.stringify(jsobject);
...to convert a JS object into a JSON string.
(See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify)
and
var jsOject = JSON.parse(jsomString);
...to convert back in the other direction.
(see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/parse)
The only time you need to worry about this not being built-in is if you're using an old browser - for example, older versions of IE. However, in this case, there are polyfill libraries like this one that you can load which will implement the above syntax for you.
If you're just trying to compose one big JSON object, you don't need to stringify one JSON object before adding it to another... So instead of doing JSON.stringify(json) you can just do json1[outerKey]=json
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=json;
}
try jsonlint.com to validate your JSON
This is valid:
{
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
This is valid too:
{
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
This isn't:
Required: {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
using JSON.stringify() is the right way of converting javascript objects to JSON string format. However if you want to put it in a variable you should do that first, later in the last step you convert to JSON string.
var output = { "Required": yourpreviousjsonvar },
jsonString = JSON.strinify(output);
EDIT:
You need to process the data first you probably won't even need the JSON string if I understand you right. (=> if however you already got a string you need it parsed first. Do it using JSON.parse(yourjsonstring))
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
having this as variable:
var a = {
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
// step 1
console.log(a.Required);
// step 2
console.log(a.Required.Center);
console.log(a.Required.Left);
// step 3
var center = a.Required.Center.split(',');
var left = a.Required.Left.split(',');
// step 4
for(var i = 0; i<center.length; i++){
console.log("doing somthing with", center[i]);
}
Here is a fiddle => use Chrome/safari/Opera's developpertools and check the console to check the output. Or use firebug (in firefox) Or IE9 or greater (F12).
Use native Javascript toSource :
var obj= new Object();
var obj1= new Object();
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
obj.innerKey=jsonValues;
}
obj1.outerKey=obj;
}
json = obj.toSource();
json1 = obj1.toSource();

How do I convert a velocity array [x, y, z] into a string to be stored in a database?

I'm trying to store a velocity vector declared as this:
me.vel = [0, 0, 0];
into a MySQL database. I assume this needs to be converted into a string before it can be stored, but that's because I don't know of any appropriate type to store it as, ex: VARCHAR, INT, STRING, etc. (If it can be stored let me know which type as this would be a simpler solution and I wouldn't have to convert into a string then back to a vector)
I've tried:
var velocityString = me.vel.join();
var velocityString = String(me.vel);
but those don't seem to work.
How can I convert this array into a string?
Thanks,
Digimas
Or you could json encode the object.
Why not store the data as three separate columns? vel_x, vel_y, vel_z (perhaps a DOUBLE). This is much cleaner and will save you the trouble of converting to/from strings all the time.
If (and I don't think it's the case) the velocity element values are fixed, you could use one of the MySQL SET or ENUM datatypes to store your Array.
Otherwise I'd go for JSON and store a JSON.encoded string in a VARCHAR field (unless you're storing light velocities)1:
/* Store: */ JSON.encode([1,2,3]); //=> "[1,2,3]"
/* Retrieve: */ JSON.parse(velocityFromSQL); //=> [1,2,3]
1 VARCHAR can contain up to 255 characters
Both of the solutions you tried should work. I get "0,0,0" for both. But as Christopher suggested before, JSON encode would work, and in my opinion is the best solution. joining or stringifying just create a comma delimited list, which with a single example as this would be ok. But if you do anything more complex you rist loosing meaning from your data (say if you array wasn't only numbers.) So if JSON.stringify/parse are available use that, otherwise [0,0,0].join(",")/"0,0,0".split(",") will work.
I would do var velString = me.vel.join(','); if you want it to be a string.
To convert it back:
var vel = velString.split(',');
for (var i = 0; i < vel.length; i++) {
vel[i] = parseFloat(vel[i]);
}
Alternatively, if you know that your users will only be using modern browsers:
var vel = velString.split(',').map(parseFloat)
I can't comment on a more appropriate datatype in MySQL. It seems like three numeric columns might make more sense unless you expect to record higher-dimension velocities in the future.
var vel = [0, 0, 0];
var vel_string = vel.join('|');
Gives you 0|0|0
Then to make it an array if you have the string outta the database:
var vel_string = '0|0|0';
var vel = vel_string.split('|');
for(var i in vel) {
vel[i] = parseInt(vel[i]);
}

JSON conversion in javascript

I'm trying to stringify a multi-array variable into a JSON string in Javascript. The
//i'm using functions from http://www.json.org/json2.js
var info = new Array(max);
for (var i=0; i<max; i++) {
var coordinate = [25 , 32];
info[i] = coordinate;
}
var result = JSON.stringify(info);
But result doesn't look like a JSON string at all. What am I doing wrong here?
You, and many in this question, are confused about the JSON specification. The string you have is a valid JSON array.
From json.org
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is
realized as an object, record,
struct, dictionary, hash table,
keyed list, or associative array.
An ordered list of values. In most languages, this is realized as
an array, vector, list, or
sequence.
Your example matches the second structure - the ordered list of values.
Also from json.org:
An array is an ordered collection of
values. An array begins with [ (left
bracket) and ends with ] (right
bracket). Values are separated by ,
(comma).
A value can be a string in double
quotes, or a number, or true or false
or null, or an object or an array.
These structures can be nested.
Doesn't leave much to the imagination. You've got a valid JSON array there. Have fun with it. But just to be annoyingly thorough:
From the RFC
RFC 4627, Section 2
2) JSON Grammar
A JSON text is a sequence of
tokens. The set of tokens includes
six structural characters, strings,
numbers, and three literal names.
A JSON text is a serialized object
or array.
JSON-text = object / array
The result looks like this for me:
[[25,32],[25,32],[25,32],[25,32],[25,32],[25,32],[25,32],[25,32],[25,32],[25,32]]
Which is fine as far as I can see. It might look a bit weird, but that is mostly because JSON is used a lot for objects, which have a slightly different notation. You can eval the string and get the array structure back though, so it looks fine to me.

Categories