I wish to name an array according to the table row containing the button that was clicked.
I get the table row thus:
var rowNum = $(this).parent().parent().index();
Now, I wish to name the array and access it.
var arrayName = 'arrTR' + rowNum;
window[arrayName] = new Array();
window[arrayName]["First"] = "Bob";
window[arrayName]["Last"] = "Roberts";
window[arrayName]["email"] = "me#there.com";
//The array should be accessible as arrTR__
alert(arrTR1["Last"]);
The alert does not work, so I am doing something wrong.
How should I refactor the code to allow me to update and access the array?
jsFiddle
What you're doing with the dynamically named variables is essentially creating an array of those variables (one for each rowNum), but giving each of those array elements its own individual named variable.
There is a much better way to do this. Instead of generating a series of dynamically named variables, make a single array or an object. Then add an element or property for each of the dynamically named variables you were going to generate.
Your test code could look like this:
var arrTR = [];
var rowNum = 1;
arrTR[rowNum] = {
First: 'Bob',
Last: 'Roberts',
email: 'me#there.com'
};
alert( arrTR[1].Last );
Alternatively, you can do something with $.data as mentioned in Johan's answer. But if you do use plain JavaScript code, use a single array as described here instead of multiple dynamically named variables.
There are several reasons to do it this way. It's cleaner and easier to understand the code, it may be faster when there are large numbers of entries, and you don't have to pollute the global namespace at all. You can define the var arrTR = []; in any scope that's visible to the other code that uses it.
Arrays and objects are made for keeping track of lists of things, so use them.
There is nothing wrong with your code, and the only place it has error is the alert since it is not defined on the first click button
see this fiddle with a little update
if(rowNum === 1)
alert(arrTR1["Last"]);
else if(rowNum === 2)
alert(arrTR2["Last"]);
fiddle
How about something like this?
$('.getinfo').click(function() {
var result = $('table tr:gt(0)').map(function(k, v){
return {
firstName: $(v).find('.fname').val(),
lastName: $(v).find('.lname').val(),
email: $(v).find('.email').val(),
}
}).get();
//update to show how you use the jQuery cache:
//1. set the value (using the body tag in this example):
$('body').data({ result: result });
//2. fetch it somewhere else:
var res = $('body').data('result');
});
Not sure how you want to handle the first row. I skip in in this case. You can access each row by result[index].
As you might have noticed, this saves all rows for each click. If you want to use the clicked row only, use the this pointer.
http://jsfiddle.net/nwW4h/4/
Related
I have a problem in deleting data from a JSON object in javascript. I'm creating this JSON dynamically and the removal shall also take place dynamically. Below is my JSON and the situation I'm in to.
{brands:[51,2046,53,67,64]}
Now, I have to remove 53 from this which I am calculating using some elements property, but I'm not able to remove the data and unable to find the solution for this situation. Please help me folks, thank you.
Try to use Array.prototyp.splice,
var data = { brands:[51,2046,53,67,64] };
data.brands.splice(2,1);
Since you want to remove an element from an array inside of a simple object. And splice will return an array of removed elements.
If you do not know the position of the element going to be removed, then use .indexOf() to find the index of the dynamic element,
var elementTobeRemoved = 53;
var data = { brands:[51,2046,53,67,64] };
var target = data.brands;
target.splice(target.indexOf(elementTobeRemoved),1);
You could write the same thing as a function like below,
function removeItem(arr,element){
return arr.splice(arr.indexOf(element),1);
}
var data = { brands:[51,2046,53,67,64] };
var removed = removeItem(data.brands,53);
I know there are a lot of questions about this, but I can't find the solution to my problem and have been on it for a while now. I have two sets of input fields with the same name, one for product codes, and one for product names. These input fields can be taken away and added to the DOM by the user so there can be multiple:
Here is what I have so far, although this saves it so there all the codes are in one array, and all the names in another:
var updatedContent = [];
var varCode = {};
var varName = {};
$('.productVariationWrap.edit input[name="varVariationCode[]"]')
.each(function(i, vali){
varCode[i] = $(this).val();
});
$('.productVariationWrap.edit input[name="varVariationName[]"]')
.each(function(i1, vali1){
varName[i1] = $(this).val();
});
updatedContent.push(varCode);
updatedContent.push(varName);
I am trying to get it so the name and code go into the same array. i.e. the code is the key of the K = V pair?
Basically so I can loop through a final array and have the code and associated name easily accessible.
I can do this in PHP quite easily but no luck in javascript.
EDIT
I want the array to look like:
[
[code1, name1],
[code2, name2],
[code3, name3]
];
So after I can do a loop and for each of the arrays inside the master array, I can do something with the key (code1 for example) and the associated value (name1 for example). Does this make sense? Its kind of like a multi-dimensional array, although some people may argue against the validity of that statement when it comes to Javascript.
I think it's better for you to create an object that way you can access the key/value pairs later without having to loop if you don't want to:
var $codes = $('.productVariationWrap.edit input[name="varVariationCode[]"]'),
$names = $('.productVariationWrap.edit input[name="varVariationName[]"]'),
updatedContent = {};
for (var i = 0, il = $codes.length; i < il; i++) {
updatedContent[$codes.get(i).value] = $names.get(i).value;
}
Now for example, updatedContent.code1 == name1, and you can loop through the object if you want:
for (var k in updatedContent) {
// k == code
// updatedContent[k] == name
}
Using two loops is probably not optimal. It would be better to use a single loop that collected all the items, whether code or name, and then assembled them together.
Another issue: your selectors look a little funny to me. You said that there can be multiple of these controls in the page, but it is not correct for controls to have duplicate names unless they are mutually exclusive radio buttons/checkboxes--unless each pair of inputs is inside its own ancestor <form>? More detail on this would help me provide a better answer.
And a note: in your code you instantiated the varCode and varName variables as objects {}, but then use them like arrays []. Is that what you intended? When I first answered you, i was distracted by the "final output should look like this array" and missed that you wanted key = value pairs in an object. If you really meant what you said about the final result being nested arrays, then, the smallest modification you could make to your code to make it work as is would look like this:
var updatedContent = [];
$('.productVariationWrap.edit input[name="varVariationCode[]"]')
.each(function(i, vali){
updatedContent[i] = [$(this).val()]; //make it an array
});
$('.productVariationWrap.edit input[name="varVariationName[]"]')
.each(function(i1, vali1){
updatedContent[i1].push($(this).val()); //push 2nd value into the array
});
But since you wanted your Code to be unique indexes into the Name values, then we need to use an object instead of an array, with the Code the key the the Name the value:
var updatedContent = {},
w = $('.productVariationWrap.edit'),
codes = w.find('input[name="varVariationCode[]"]'),
names = w.find('input[name="varVariationName[]"]');
for (var i = codes.length - 1; i >= 0; i -= 1) {
updatedContent[codes.get(i).val()] = names.get(i).val();
});
And please note that this will produce an object, and the notation will look like this:
{
'code1': 'name1',
'code2': 'name2',
'code3': 'name3'
};
Now you can use the updatedContent object like so:
var code;
for (code in updatedContent) {
console.log(code, updatedContent[code]); //each code and name pair
}
Last of all, it seems a little brittle to rely on the Code and Name inputs to be returned in the separate jQuery objects in the same order. Some way to be sure you are correlating the right Code with the right Name seems important to me--even if the way you're doing it now works correctly, who's to say a future revision to the page layout wouldn't break something? I simply prefer explicit correlation instead of relying on page element order, but you may not feel the need for such surety.
I don't like the way to solve it with two loops
var updatedContent = []
$('.productVariationWrap.edit').each(function(i, vali){
var $this = $(this)
, tuple = [$this.find('input[name="varVariationCode[]"]').val()
, $this.find('input[name="varVariationName[]"]').val()]
updatedContent.push(tuple)
});
I have created a mini template that holds and <h2> & <h3>, I have created a loop that adds .inner everytime i%2 === 0, what i would like to do is split up the data being outputted to follow the same kind of rule so when i%2 === 0 add .inner and also split the object properties so each .inner should display 2 templated object properties. Can anyone advise on how this can be achieved? Also my templated items seem to return undefined?
Demo here http://jsbin.com/otirax/13/edit
Your code can be improved in many ways. The selector here:
$('.inner').append(temp);
should actually be $(".inner:last"), otherwise it affects all ".inner" objects created so far. Better yet, save a newly created div in a variable:
inner = $('<div class="inner"></div>').appendTo($('#ctn'));
and then simply use the var, thus saving an expensive selector operation:
inner.append(...);
Another improvement is to automate template rendering. Consider the following function: it populates arbitrary {{tags}} from an object:
function render(template, values) {
return template.replace(
/{{(\w+)}}/g,
function($0, $1) { return values[$1] });
}
Complete example: http://jsbin.com/iviziz/2/edit
. Let us know if you have questions.
Templated items seem to return undefined:
var temp = template.replace(/name/ig, data.name)
.replace(/age/ig, data.age);
Should be as below due to them being an array.
var temp = template.replace(/name/ig, data[i].name)
.replace(/age/ig, data[i].age);
I assume that thesonglessbird's reply was clear enough, but just to give a proper answer, instead of
var temp = template.replace(/\{\{name\}\}/ig, data.name)
.replace(/\{\{age\}\}/ig, data.age);
you would need to have
var temp = template.replace(/\{\{name\}\}/ig, data[i].name)
.replace(/\{\{age\}\}/ig, data[i].age);
you can see an example here http://jsbin.com/otirax/16/edit
Aside of that, schemantically a 'template' should not be placed inside script tags as it isn't a script.
ok. I have a dropdown. well call it dropdownA. I have several arrays already fashioned, that i want to loop through, and put each individual value out onto the page into it's own input field, based on the selection in the dropdown. I know how to put together the loop to get the values out onto the page. anyway, here is the meta code.
meta1array=new Array('','','','','','');
meta2array=new Array('','','','','','');
meta3array=new Array('','','','','','');
function metacode(id){
{
var a=get.the.dd.selIndex;
var b=get.the.dd.options[a].value; //comes back as 'meta1'. other opts are meta2, meta3
var c=b+'array';
for(i=0;i<c.count;i++)
{
loop here to popout values
}
}
i have looked everywhere, and i haven't come up with anything. I also admit that my brain is starting to mushify from a few weeks straight of coding, and this is the first time i have come across this. so, please. i would be greatful for any help.
Global variables are members of the window object.
var c = window[b + 'array'];
It might be wise to make your arrays members of some other object though, for tighter scoping (avoid cluttering the global namespace).
metaobject = {
meta1array: ['','','','',''],
meta2array: ['','','','',''],
meta3array: ['','','','','']
};
// snip
var arr = metaobject[b + 'array'];
for(var i=0;i<arr.length;i++) {
//do work
}
Check out the fiddle using jquery here.
I'm writing a jquery-plugin, that changes a css-value of certain elements on certain user-actions.
On other actions the css-value should be reseted to their initial value.
As I found no way to get the initial css-values back, I just created an array that stores all initial values in the beginning.
I did this with:
var initialCSSValue = new Array()
quite in the beginning of my plugin and later, in some kind of setup-loop where all my elements get accessed I used
initialCSSValue[$(this)] = parseInt($(this).css('<CSS-attribute>'));
This works very fine in Firefox.
However, I just found out, that IE (even v8) has problems with accessing the certain value again using
initialCSSValue[$(this)]
somewhere else in the code. I think this is due to the fact, that I use an object ($(this)) as a variable-name.
Is there a way arround this problem?
Thank you
Use $(this).data()
At first I was going to suggest using a combination of the ID and the attribute name, but every object might not have an ID. Instead, use the jQuery Data functions to attach the information directly to the element for easy, unique, access.
Do something like this (Where <CSS-attribute> is replaced with the css attribute name):
$(this).data('initial-<CSS-attribute>', parseInt( $(this).css('<CSS-attribute>') ) );
Then you can access it again like this:
$(this).data('initial-<CSS-attribute>');
Alternate way using data:
In your plugin, you could make a little helper function like this, if you wanted to avoid too much data usage:
var saveCSS = function (el, css_attribute ) {
var data = $(el).data('initial-css');
if(!data) data = {};
data[css_attribute] = $(el).css(css_attribute);
$(el).data('initial-css', data);
}
var readCSS = function (el, css_attribute) {
var data = $(el).data('initial-css');
if(data && data[css_attribute])
return data[css_attribute];
else
return "";
}
Indexing an array with a jQuery object seems fishy. I'd use the ID of the object to key the array.
initialCSSValue[$(this).attr("id")] = parseInt...
Oh please, don't do that... :)
Write some CSS and use the addClass and removeClass - it leaves the styles untouched afterwards.
if anybody wants to see the plugin in action, see it here:
http://www.sj-wien.at/leopoldstadt/zeug/marcel/slidlabel/jsproblem.html