"Key" object in jQuery does not work correctly - javascript

So I have been trying to get this small bit of code to work. However, I'm not sure if it's my syntax or if I have done this incorrectly. The goal of this code is for the user to input a string like "H2" or "Li" and return the number associated with that string in the div "testing." When I run the code, it does not return anything.
<form>
<input type="text" name="atomNameOne"/>
</form>
<button name="moleRatios">Submit!</button>
<br/>
<br/>
<br/>
<div id="testing"></div>
This is the jQuery code associated with my code.
$('button[name=moleRatios]').click(function(){
var compound = {
H2 = 2.01594,
Li = 6.939,
Be = 9.0122,
B = 10.811
}
var search = function(name) {
for(var key in compound) {
if(compound[key] === name) {
return compound[key];
}
}
};
var $atomValueOne = search($('input[name=atomNameOne]').val());
$('#testing').text($atomValueOne);
});

there is a wrong syntax there:
var compound = {
H2 = 2.01594,
Li = 6.939,
Be = 9.0122,
B = 10.811
}
should be
var compound = {
H2: 2.01594,
Li: 6.939,
Be: 9.0122,
B: 10.811
}
and then
compound[key] will return 2.01594 if key is H2, maybe you want
if(compound[key] === name)
to be
if(key == name)
instead
The rest should be the same

replace
if(compound[key] === name)
with
if(key === name)
and also correct the object syntax as given in other answers

The correct way to define an object is
var compound = { H2: 2.01594, Li : 6.939, Be: 9.0122, B : 10.811 }
as a propertyName : propertyValue format.
To access the propertyName as a string, use-
var search = function(name) {
for(var key in compound) {
if(key === name) {
return compound[key];
}
}
};
where the iterator 'key' will always give the name(as a string) of the property and the format objectName[iterator] will always give the value of the property.

Related

How to loop through all the array of objects?

I have an Array of Object to be used to draw a HTML Table:
Array(5)
0: Object
id: 4
name: Sand Jane
address: Green Sand Street
...
...
...
1: Object
2: Object
...
...
...
I am able to do a single name column defined search with
const temp = this.temp.filter(function (d) {
return d.name.toLowerCase().indexOf(val) !== -1 || !val;
});
temp will contain the filtered data of this.temp
Now I just can't figure out how to loop through all object keys (id,name,address...) so that I can do a global column search in the Table.
UPDATE: I have tried this,
const temp = [];
this.temp.forEach(element => {
for (let key in element) {
if (element.hasOwnProperty(key)) {
let v = element[key];
if (v.toString().toLowerCase().indexOf(val) !== -1 || !val) {
temp.push(element);
}
}
}
});
It works but with performance issues.
RESOLVED: Putting a break after temp.push fixed this issue. Thank you all for the guidelines and references.
temp.forEach(item=>{
for(let key in item) {
//item[key] gives you access to each value
}
})
You can iterate through for loops or even you can usefor loop inside a for loop. Either way it's self explanatory.
var dictionary = {
"employee1":[
{"id":"0","name":"Google"},
{"id":"1","name":"eBay"}
],
"employee2": [
{"id":"2","name":"Yahoo"},
{"id":"3","name":"Facebook"}
]
};
var employee1 = dictionary.employee1;
var employee2 = dictionary.employee2;
for ( var i in employee1) {
var id = employee1[i].id;
var name = employee1[i].name;
console.log(id);
console.log(name);
}
for ( var i in employee2) {
var id = employee2[i].id;
var name = employee2[i].name;
console.log(id);
console.log(name);
}

Updating multi-level object value from dataset value

difficult one to explain.
var options = {
container: node,
pin: {
size: [50, 50],
anchor: 0,
animation: 0
}
}
Let's use the above Object as an example. I want to loop through the dataset from an HTMLElement and update the above values using the dataset values. This removed the need to manually check if the dataset value exists and then replace the value.
What I have got so far:
(function() {
for( const data in node.dataset ) {
// First remove the 'map' as this isn't required, then split any values with multiple capitals,
// as these corrospond to multilevel object values.
var key = (data.replace("map", "")).split(/(?=[A-Z])/), value = node.dataset[data];
const findOption = function() {
};
// Check that there is a value
if (value !== null) {
const opt = null;
// Find the corresponding default option
}
}
}.call(_));
Here is the HTML with the dataset attributes, this should help everything make more sense:
<div data-map data-map-offset='[10, 10]' data-map-pin-size='[20, 20]'></div>
As you can see above the attribute data-map-pin-size needs to replace the value within the object, but i'm not sure how to reference that object as usually I would either do options.pin.size or options['pin']['size']. But due to this loop not knowing how deep it needs to go I can't always rely on this, I need some kind of callback function right? Which is why I started findOption() however i'm not too sure where to go from there!
Edit:
This is what I have got so far now, however this isn't updating the options object, it's just setting the value of opt.
(function() {
for( const data in node.dataset ) {
// First remove the 'map' as this isn't required, then split any values with multiple capitals,
// as these corrospond to multilevel object values.
var key = (data.replace("map", "")).split(/(?=[A-Z])/), value = node.dataset[data];
// Pin Size
const findOption = function(val) {
return options[val.toLowerCase()];
};
// Check that there is a value
if (value !== null) {
var opt = null;
// Find the corresponding default option
for (var x = 0; key.length > x; x++) {
opt = findOption(key[x]);
}
opt = value;
}
}
console.log(options);
}.call(_));
If you convert your options to this format:
var options = {
container: node,
pinSize: [50, 50],
pinAnchor: 0,
pinAnimation: 0
}
your implementation would be able to be simplified to this:
for (const key in node.dataset) {
const opt = key.replace(/^map(.)/, (match, c) => c.toLowerCase())
options[opt] = JSON.parse(node.dataset[key])
}
assuming you intend to use JSON-compliant values in your HTML data- attributes.
Here I added a recursive function to set the value by finding the specific key on the options object. You can see that for any length of data set attribute the values are getting set properly.
This works with any kind of options object format dynamically.
I added an extra sample as well to demonstrate it.
(function() {
//A function to set the value on a nested object by
//recursively finding the key
function setValue(object, key, value) {
var value;
Object.keys(object).some(function(k) {
if (k === key) {
object[k] = value;
}
if (object[k] && typeof object[k] === 'object') {
setValue(object[k], key, value);
}
});
}
node = document.getElementById("elem");
var options = {
container: node,
pin: {
size: [50, 50],
anchor: 0,
animation: 0,
value: {
xy: [1, 1]
}
}
}
for (const data in node.dataset) {
// First remove the 'map' as this isn't required, then split any values with multiple capitals,
// as these corrospond to multilevel object values.
var keys = (data.replace("map", "")).split(/(?=[A-Z])/),
value = node.dataset[data];
var findOption = function() {
keys.forEach(function(key, index) {
if (index == keys.length - 1) {
setValue(options, key.toLowerCase(), value);
}
})
}();
// Check that there is a value
if (value !== null) {
const opt = null;
// Find the corresponding default option
}
}
console.log(options);
}.call());
<div data-map data-map-offset='[10, 10]' data-map-pin-size='[20, 20]' data-map-pin-value-xy='[0, 5]' id="elem"></div>

How to write case condition expression in DustJS?

I have a array type in Javascript:
var type=[0,1,2,3,4,5];
The corresponding key value pair collection is actually like this;
[{0:'Pointer'},{1:'Line'},{2:'Oval'},{3:'Rectangle'},{4:'Ellipse'},{5,'Star'}]
My .dust file displays the {type} mark, how should I display their corresponding values?
You may use a custom filter. The approximate implementation would be:
var mapping = {
'0':'Pointer',
'1':'Line',
'2':'Oval',
'3':'Rectangle',
'4':'Ellipse',
'5':'Star'
};
dust.filters['typeFilter'] = function(value) {
return mapping[value] || '';
}
And in you template: {type|typeFilter}
It's a bit simpler to store the mapping in an object than array. For you array version it would be like:
var mapping = [{0:'Pointer'},{1:'Line'},{2:'Oval'},{3:'Rectangle'},{4:'Ellipse'},{5:'Star'}];
dust.filters['typeFilter'] = function(value) {
var typeId = parseInt(value);
for(var len = mapping.length - 1; len >=0; len--) {
if (mapping[len].hasOwnProperty(typeId)) {
return mapping[len][typeId];
}
}
return '';
}
A bit more information here

create array, use $.each to loop, and add value if not in array

I have a bunch of .defined in a text and want to create an array of unique values with javascript. So basically, for each anchor with class defined, I want to first check the array to see if the pair already exists. If exists, go to next anchor. If does not exist, add to array. This is the code I have tried using, but it does not remove duplicate values.
var arr = new Array();
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if(spanishWord in arr) {
console.log("do nothing");
} else {
arr.push({key: spanishWord, value: englishWord});
y++;
}
For example, I have these tags in the text:
<a title="read">Leer</a>
<a title="work">Trabajar</a>
<a title="like">Gustar</a>
<a title="read">Leer</a>
<a title="sing">Cantar</a>
<a title="like">Gustar</a>
And I would like my array to look like:
Spanish Word | English Word
Leer read
Trabajar work
Gustar like
Cantar sing
but instead it looks like:
Spanish Word | English Word
Leer read
Trabajar work
Gustar like
Leer read
Cantar sing
Gustar like
Any ideas?
I would do this in two steps.. one to eliminate duplicates, and one to create the array:
http://jsfiddle.net/uN4js/
var obj = {};
$('a.defined').each(function() {
obj[this.text] = this.title;
});
var arr = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop))
arr.push({key: prop, value: obj[prop]});
};
console.log(arr);
If the object is sufficient and you don't really need an array, you could stop after the object is created.
You can probably just use a javascript object here:
var dict = {};
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
dict[spanishWord] = englishWord;
}
And there isn't really a need for unique checks, since newer values will just overwrite the older ones. If you don't want that behaviour, you can do this:
var dict = {};
y = 0;
$("a.defined").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if (!(spanishWOrd in dict)) {
dict[spanishWord] = englishWord;
}
}
Javascript's in operator is not used for testing inclusion, it's used for iteration in a for .. in .. loop.
Other answers have suggested correctly that you need either .indexOf or JQuery's $.inArray method to test inclusion in an array, but there is a simpler (and faster) way of solving this problem: use a dictionary of key/value pairs instead!
var dict = {};
$("a.defined").each(function() {
dict[this.textContent] = this.title;
});
Afterwards, you can use for key in dict to iterate over the list of unique Spanish words, and dict[key] to get the corresponding English translation.
Try this:
JavaScript
var arr = {};
$("a").each(function() {
var spanishWord = this.text;
var englishWord = this.title;
if(spanishWord in arr) {
console.log("do nothing");
} else {
arr[spanishWord] = englishWord;
}
});
console.log(arr);

How to serialize a form into an object (with tree structure)?

I have a form
<form>
<input type="text" name="Name" />
<input type="checkbox" name="Feature.Translate" />
<input type="checkbox" name="Feature.Share" />
<input type="submit" value="Convert into an object" />
</form>
I want to convert it in an object
{
Name: "John Connor's Terminator",
Feature:
{
Translate: true // if checked
// Share wasn't checked
}
}
How can I map the form to an object that has this tree structure?
Add this method to help you build the tree
// add keys to an object as a tree
// ["a", "b", "c"] will generate
// a { b: { c: def } }
// def is the value of the leaf node
var AddToTree = function(obj, keys, def)
{
for (var i = 0, length = keys.length; i < length; ++i)
obj = obj[keys[i]] = i == length - 1 ? def : obj[keys[i]] || {};
};
Create a function for a jQuery selector that will convert the form in an object
$.fn.serializeObject = function()
{
var o = {}; // final object
var a = this.serializeArray(); // retrieves an array of all form values as
// objects { name: "", value: "" }
$.each(a, function() {
var ns = this.name.split("."); // split name to get namespace
AddToTree(o, ns, this.value); // creates a tree structure
// with values in the namespace
});
return o;
};
With these two functions define you can set an event on the submit button:
$(":submit").click(function(e){
// contains the object from the form
// respecting element namespaces
var obj = $("form").serializeObject();
});
Something like the following should work:
function serializeData() {
//this is where we'll store our serialized data
var serializedData = {};
//iterate over input, select, and textarea elements
jQuery("input, select, textarea").each(function(index) {
var $element = jQuery(this);
var name = $element.attr("name");
//we only want to serialize the element if it has a 'name' attribute
if(typeof name != "undefined") {
//split on the . to get an array
var parts = name.split(/\./);
//start building the serialized data
var currentPart = serializedData;
for(var i = 0; i < parts.length; i++) {
//if this particular element doesn't already exist in our hash, create it
//and initialize it to an empty hash
if(typeof serializedData[parts[i]] == "undefined") {
currentPart[parts[i]] = {};
}
//if we're currently looking at the very last element in the array then
//it means that we need to set its value to the value of the corresponding
//input element. Otherwise, it means that there are still keys within the
//array and so we set `currentPart` to the new hash that we just created
if(i == parts.length - 1) {
//if the element is a checkbox or a radio, we need to see if it's checked
//instead of looking at its value
if($element.attr("type").toLowerCase() == "checkbox" || $element.attr("type").toLowerCase() == "radio") {
currentPart[parts[i]] = $element.is(":checked");
}
else {
currentPart[parts[i]] = $element.val();
}
}
else {
currentPart = currentPart[parts[i]];
}
}
}
});
console.log(serializedData);
}
Check out the fiddle.
All you need to do now is to bind serializeData to the submit event on the form.

Categories

Resources