I am receiving a html form. This works fine when 2 or more elements in array, but when only one element is received I get error users[t] is null in fireBug?
var users = form.elements["uname[]"];
for(t in users) {
dataString += "User: "+users[t].value+"\n"
}
this solved it:
if( typeof users.value === 'string' ) {
users = [ users ];
}
I know this is an old question but I stumbed across it while searching for something else. Anyway, I thought I'd provide another answer for anyone else who stumbled across this.
Rather than checking the type to see if it is an array or not and then optionally encasing the value in a new array, you can use Array.prototype.concat().
Its syntax is
var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
where any of those values can be either an array or a single value.
In your specific case, you can start with an empty array and concatenate your form input, which will work whether you get a single value or an array:
var users = [].concat(form.elements["uname[]"]);
or
users = [].concat(users);
You could check if the variable is a string and convert it to an array:
if( typeof users === 'string' ) {
users = [ users ];
}
For iterating arrays for-in should be avoided, that statement is meant to enumerate object properties. You could try using a better loop, something like:
var userCount = users.length;
for (var i = 0; i < userCount; i++) {
dataString += "User: "+users[i].value+"\n"
}
You could also base a test on the length. If the object is single it will return undefined for length.
var userCount = users.length; //Get user count
if ( userCount == undefined ) { //Returned undefined if not an array.
users = [ users ]; //Convert to array
}
Related
Im using the following code,
jQuery.each(aDataSel, function(index, oData) {
oPushedObject = {};
aSelectedDataSet.push(fnCreateEnt(aProp, oData, oPushedObject));
});
This is aSelectedDataSet values
and this is the values of OData
What I need is that before I do the push is to fill the listTypeGroup & listTypeGroupDescription (with the red arrow ) with values that Are inside the oData -> ListTypeGroupAssigment -> result (listTypeGroup & listTypeGroupDescription) , The index is relevant since I want to add just the value of the index in each iteration (since this code is called inside outer loop and the index determine the current step of the loop) ,How it can be done nicely?
The result contain 100 entries (always) and the a selected data will have 100 entries at the end...
Update :)
Just to be clear In the pic I show the values which is hardcoded for this run but the values can be any values, we just need to find the match between the both objects values...
I mean to find a match between to_ListTypeGroupAssigment in both object (which in this case exist ) and if in oData there is result bigger then one entry start with the matching ...
UPDATE2 - when I try Dave code the following happen for each entry,
This happen in the Jquery.extend line...any idea how to overcome this?
The following hard-coded of Dave:-) work perfect but I need generic code which doesnt refer to specific field name
jQuery.each(aDataSet, function(index, oData) {
oPushedObject = {};
fnCreatePushedEntry(aProperties, oData, oPushedObject);
var result = oData.to_ListTypeGroupAssignment.results[index];
oPushedObject.to_ListTypeGroupAssignment = {
ListTypeGroup: result.ListTypeGroup,
ListTypeGroupDescription: result.ListTypeGroupDescription
};
aSelectedDataSet.push(oPushedObject);
});
Im stuck :(any idea how to proceed here ?what can be wrong with the extend ?
should I use something else ? Im new to jQuery...:)
I think that this happen(in Dave answer) because the oData[key] is contain the results and not the specified key (the keyValue = to_ListTypeGroupAssignment ) which is correct but we need the value inside the object result per index...
var needValuesForMatch = {
ListTypeGroup: 'undefined',
ListTypeGroupDescription: 'undefined',
}
//Just to show that oPushedObject can contain additional values just for simulation
var temp = {
test: 1
};
//------------------This object to_ListTypeGroupAssigment should be filled (in generic way :) ------
var oPushedObject = {
temp: temp,
to_ListTypeGroupAssignment: needValuesForMatch
};
oPushedObject is one instance in aSelectedDataSet
and after the matching I need to do the follwing:
aSelectedDataSet.push(oPushedObject);
Is this what you're after:
OPTION ONE - DEEP CLONE FROM oData TO aSelectedDataSet
aSelectedDataSet.forEach(function(currentObject,index){
for (var childObject in currentObject) {
if (! currentObject.hasOwnProperty(childObject))
continue;
var objectToClone = oData[childObject]['results'][index];
if(objectToClone)
$.extend(true,currentObject[childObject],objectToClone);
}
});
Here is your data in a fiddle with the function applied: https://jsfiddle.net/hyz0s5fe/
OPTION TWO - DEEP CLONE FROM oData ONLY WHERE PROPERTY EXISTS IN aSelectedDataSet
aSelectedDataSet.forEach(function(currentObject,index){
for (var childObject in currentObject) {
if (! currentObject.hasOwnProperty(childObject))
continue;
if(typeof currentObject[childObject] !== 'object')
continue;
for(var grandChildObject in currentObject[childObject]) {
var objectToClone = oData[childObject]['results'][index][grandChildObject];
if(typeof objectToClone === 'object') {
$.extend(true,currentObject[childObject][grandChildObject],objectToClone);
} else {
currentObject[childObject][grandChildObject] = objectToClone;
}
}
}
Fiddle for option 2: https://jsfiddle.net/4rh6tt25/
If I am understanding you correctly this should just be a small change:
jQuery.each(aDataSel, function(index, oData) {
oPushedObject = {};
fnCreateEnt(aProp, oData, oPushObj);
//get all the properties of oData and clone into matching properties of oPushObj
Object.getOwnPropertyNames(oData).forEach(function(key) {
if (oPushObj.hasOwnProperty(key)) {
//oPushObj has a matching property, start creating destination object
oPushObj[key] = {};
var source = oData[key];
var destination = oPushObj[key];
//can safely assume we are copying an object. iterate through source properties
Object.getOwnPropertyNames(source).forEach(function(sourceKey) {
var sourceItem = source[sourceKey];
//handle property differently for arrays
if (Array.isArray(sourceItem)) {
//just copy the array item from the appropriate index
destination[sourceKey] = sourceItem.slice(index, index + 1);
} else {
//use jQuery to make a full clone of sourceItem
destination[sourceKey] = $.extend(true, {}, sourceItem);
}
});
}
});
aSelectedDataSet.push(oPushedObject);
});
It is unclear what exactly your fnCreateEnt() function returns though. I am assuming it is the populated oPushObj but it's not entirely clear from your question.
I have a data with certain rule. I want to create a json object to manage the rule. There is problem to create a json object as my need. Here my array data.
$scope.data = ["Crust^Pan^Medium=NA", "Crust^Pan^Large=NA", "Crust^Thin Crust^Medium=10.50"]
I want a output like this:
{
"Pan": {
"Medium": NaN,
"Large": NaN,
},
"Thin Crust": {
"Medium": 10.50
}
}
Here my code,
$scope.crustRule = {};
for(var i=0; i<$scope.data.length; i++) {
var tempCrust = {};
var trimOne = $scope.data[i].split('^');
var trimTwo = trimOne[2].split('=');
if(trimOne[0] == 'Crust') {
tempCrust[trimTwo[0]]=parseFloat(trimTwo[1]);
$scope.crustRule[trimOne[1]].push(tempCrust);
}
}
console.log($scope.crustRule);
You first need to create an object $scope.crustRule[trimOne[1]] before you can push objects into it. Something like
$scope.crustRule[trimOne[1]] = {};
$scope.crustRule[trimOne[1]].push(tempCrust);
the push function has to exist. you can grab it from the Array property if you want.
only do this if it has to be in an object structure
var x = {length:0,push:Array.prototype.push};
x.push("jump");
console.log(x);//Object {0: "jump", length: 1}
I go over the mininmum requirement for some array functions to work on an object:
Mimic the structure of a javascript array object
EDIT:
I noticed your reuirements are need an object without a length and string index based instead of number index based. going to test something
darn I was hoping something wild was already there and tried
var x = {};
x += {"BadGuy": "Joker"};
console.log(x)//[object Object][object Object] //:(
so I made my own push function
var x = {push:ObjPush};
x.push("jump");//Object cannot add (string) yet Coming soon
y = {"BadGuy": "Joker"};
x.push(y);
console.log(x);//{"BadGuy": "Joker"};
function ObjPush(obj)
{
if ((typeof obj).toLowerCase() == "object")
{
for (var i in obj)
{
this[i] = obj[i];
}
}
else
{
console.log("Object cannot add (" + typeof obj + ") yet\n Coming soon");
}
}
Note:
I haven't added any handling to check for same properties. so any properties with the same name will override original properties.
EDIT:
I integrated my code with yours and got a strange output unfortunately.
for some reason instead of adding medium and large as properties to the inner objects it only adds the last 1 for example i get the output
{"Pan":{"Large":null},"Thin Crust":{"Medium":10.5}}
EDIT:
OK I found where my issue was. I get the expected output now. added a check to make sure that $scope.crustRule[trimOne[1]] is only initialized if it doesnt exist yet.
if(typeof $scope.crustRule[trimOne[1]] == "undefined")
$scope.crustRule[trimOne[1]] = {push:ObjPush};
I have two fields I need to pull data from in SQL and put that into an array or list that I can loop through. Then for each loop, I do something based on both the fields for each index. What is the best method for this? I thought maybe a dictionary or possibly creating an object?
Right now I pull the fields into two seperate arrays, and I loop through both at the same time, but I am finding that sometimes one array has a blank value, and then they get out of sync and I have issues. This seems like a terrible implementation anyway.
How can I put these into a key value pair and then act on the data?
Edit: I should note that my SQL code just returns a bunch of comma seperated values. So it was easy to create an array out of those, but its proving more difficult to create anything else such as an object because I get all the values at one time.. :(
var equipIDArray = //SQL Gathering code here
var equipTypeArray = //SQL gathering code here
for(var cnt = 0; cnt < equipIDArray.length; cnt++){
alert(cnt);
if(isNaN(equipIDArray[cnt]) === true){
equipIDArray[cnt] = '';
}
switch(equipTypeArray[cnt]){
case 'Blower' :
alert('test1');
break;
case 'Dehumidifier' :
alert('test2');
break;
default :
alert('default');
}
}
It' easy to translate your arrays into an object if they just represent key/value pairs. Then you have an object you can use like a dictionary:
var equipIDArray = ["Blower","Humidifier","Lawn Mower"];
var equipTypeArray = ["Leaf blower","Whole House Humidifier","Honda Brand"];
var equipment = {};
for(var i = 0; i < equipIDArray.length; i++) {
equipment[equipIDArray[i]] = equipTypeArray[i];
}
for(property in equipment) {
console.log(property + " : " + equipment[property]);
alert(property + " : " + equipment[property]);
}
This is the code:
var groups = {
"JSON":{
"ARRAY":[
{"id":"fq432v45","name":"Don't use me."},
{"id":"qb45657s","name":"Use me."}
]
}
}
I want to get the name value where the id is "qb45657s" how could this be accomplished? I figured the obvious loop through all of the array and check if it's equal but is there an easier way?
Edit: I cannot change "Array" to an object because I need to know the length of it for a different function.
You can simply filter on the given id:
groups["JSON"]["ARRAY"].filter(function(v){ return v["id"] == "qb45657s"; });
This will return [{"id":"qb45657s","name":"Use me."}]
Assuming you had a valid JSON string like this (note I say valid, because you need an enclosing {} or [] to make it valid):
var json = '{"JSON":{
"ARRAY":[
{"id":"fq432v45","name":"Don't use me."},
{"id":"qb45657s","name":"Use me."}
]
}
}';
You would just parse it into an actual object like this:
var jsonObj = JSON.parse(json); // makes string in actual object you can work with
var jsonArray = jsonObj.JSON.ARRAY; // gets array you are interested in
And then search for it like:
var needle = 'qb45657s';
var needleName;
for (var i = 0; i < jsonArray.length; i++) {
if (jsonArray[i].id === needle) {
needleName = jsonArray[i].name;
}
}
I'm trying to break up a string like this one:
fname=bill&mname=&lname=jones&addr1=This%20House&...
I want to end up with an array indexed like this
myarray[0][0] = fname
myarray[0][1] = bill
myarray[1][0] = mname
myarray[1][1] =
myarray[2][0] = lname
myarray[2][1] = jones
myarray[3][0] = addr
myarray[3][1] = This House
The url is quite a bit longer than the example. This is what I've tried:
var
fArray = [],
nv = [],
myarray = [];
fArray = fields.split('&');
// split it into fArray[i]['name']="value"
for (i=0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push(nv[0],nv[1]);
nv.length = 0;
}
The final product is intended to be in 'myarray' and it is, except that I'm getting a one dimensional array instead of a 2 dimensional one.
The next process is intended to search for (for example) 'lname' and returning the index of it, so that if it returned '3' I can then access the actual last name with myarray[3][1].
Does this make sense or am I over complicating things?
Your line myarray.push(nv[0],nv[1]); pushes two elements to the array myarray, not a single cell with two elements as you expect (ref: array.push). What you want is myarray.push( [nv[0],nv[1]] ) (note the brackets), or myarray.push(nv.slice(0, 2)) (ref: array.slice).
To simplify your code, may I suggest using Array.map:
var q = "foo=bar&baz=quux&lorem=ipsum";
// PS. If you're parsing from a-tag nodes, they have a property
// node.search which contains the query string, but note that
// it has a leading ? so you want node.search.substr(1)
var vars = q.split("&").map(function (kv) {
return kv.split("=", 2);
});
For searching, I would suggest using array.filter:
var srchkey = "foo";
var matches = vars.filter(function (v) { return v[0] === srchkey; });
NB. array.filter will always return an array. If you always want just a single value, you could use array.some or a bespoke searching algorithm.
for (var i = 0; i < fArray.length; i++) {
nv = fArray[i].split('=');
myarray.push([nv[0],nv[1]]);
}
nv.length = 0; is not required, since you're setting nv in each iteration of the for loop.
Also, use var i in the for-loop, otherwise, you're using / assigning a global variable i, that's asking for interference.