I am trying to dynamically create a key in a JavaScript object with a jQuery selector:
{
$("form").children("input[type=hidden]").attr("name"): $("form").children("input[type=hidden]").val()
}
This is breaking though. Is it possible to dynamically create a key this way?
You can do it in two statements :
var obj = {};
obj[$("form").children("input[type=hidden]").attr("name")]
= $("form").children("input[type=hidden]").val();
I'd personally write it like this to avoid recreating the jQuery set:
var obj = {}, $obj = $("form").children("input[type=hidden]");
obj[$obj.attr("name")] = $obj.val();
Note also that this only makes sense if the jQuery set contains exactly one element.
You can also make it work with multiple fields at once:
var obj = {};
$('form > input[type="hidden"]').each(function (i, el) {
obj[el.name] = el.value;
});
Another more fancy version in case if you have only one hidden field:
var obj = $('form > input[type="hidden"]').serializeArray()[0];
Related
the problem is that I have multiple objects with the same id. As you can see this works when it comes to removing all the items with the same id. How I can remove the objects one by one no matter if they are the same ID...thanks
individualObjects:[],
actions:{
increment:function(){
var obj = this.get('object');
this.get('individualObjects').pushObject(obj);
},
decrement:function(){
var obj = this.get('object');
var filter = this.get('individualObjects').findBy('obj_id', obj.get('obj_id'));
this.get('individualObjects').removeObject(filter);
}
}
Well to filter array you would need to use Array.filter to find out the items that do not belong in the "individualObjects" and later simply remove them by using "removeObjects"
decrement:function(){
var objects = this.get('individualObjects')
var notWanted = objects.filterBy('obj_id', this.get('object.obj_id'));
this.get('individualObjects').removeObjects(notWanted);
}
and solution 2
decrement:function(){
var removeObj = this.get('object');
var objects = this.get('individualObjects')
// As the condition is true given object is returned
var notWanted = objects.filter(obj => { return obj.get('obj_id') === removeObj.get('obj_id') });
this.get('individualObjects').removeObjects(notWanted);
}
Ok so you want to remove items one by one. Weird but can be accomplished
first get the length for
var notWantedCount = objects.filterBy('obj_id', this.get('object.obj_id')).length;
Now
for(var i=0; i <= notWantedCount; i++) {
var toRemove = individualObjects.findBy('obj_id', obj.get('obj_id'));
individualObjects.removeObject(toRemove);
// Make some custom actions one by one.
}
I don't know ember, but you'll want to do a foreach on the array, and then test for id on each one. It should be something like this:
decrement:function(){
var obj = this.get('object');
self = this;
this.get('individualObjects').each(function(individualObject) {
if (individualObject.get('obj_id') == obj.get('obj_id'))
... you want to do something here? ...
self.get('individualObjects').removeObject(individualObject);
}
}
That way you can remove each object individually. Running any necessary code before or after it's removed. If you want to sort it first, you can do that before running the each function.
Being a rookie at JavaScript, I stumbled upon this simple issue where I need to create an object for each item in an array.
More specifically, I want to create a WYSIWYG text editor for some textareas and then listen to these editor objects for input.
The code for one element would be:
// Make an element a text editor area.
var editorArea = new Edicy.TextEditorView({el: $('.foo')});
// Save on input
editorArea.editor.on('aftercommand:composer', function() {
pageData.set('key', 'value');
});
As I have many of these areas, I would like to use jQuery.each() to initiate these text editors and according unique listeners, using the data-id attribute of the elements:
$('#c-success-tabs-content .tab-pane').each(function(){
var successID = $(this).attr('data-id');
successesList.push(successID);
var editorArea[successID] = new Edicy.TextEditorView({el: $('.foo')});
editorArea[successID].editor.on('aftercommand:composer', function() {
pageData.set('key', 'value');
});
});
As the naming scheme "var editorArea[successID]" and from that the listener "editorArea[successID]" are not possible in JavaScript, what would be the optimum solution?
Use an object:
var editorAreas = {}
$('#c-success-tabs-content .tab-pane').each(function(){
var successID = $(this).attr('data-id');
successesList.push(successID);
editorAreas[successID] = new Edicy.TextEditorView({el: $('.foo')});
editorAreas[successID].editor.on('aftercommand:composer', function() {
pageData.set('key', 'value');
});
});
for(var id in editorAreas){
console.log(id, editorAreas[id])
}
Its just your syntax that is wrong; you can have an array of editors
var editorArea = []; // declare globally
and then
editorArea[successID] = new Edicy.TextEditorView({el: $('.foo')});
I have a input elements in html with two important attributes: id, and parentElementId.
I want to create a map/dictionary that looks like this: "id : parentElementId".
var parent = $(".people-autocomplete").map( function(){ return $(this).attr('id')+':'+$(this).attr('parent'); }).get() ;
for know I'm putting the values into a string, which I parse later on in the code. I presume there is a more elegant solution than this.
Use an object:
var obj = {};
$(".people-autocomplete").each(function() {
obj[$(this).attr('id')] = $(this).attr('parent');
});
You can then access the parent of a specific id:
var parent = obj.idName;
or through a string:
var idStr = 'idName';
var parent = obj[idStr];
And you can loop through:
for (idStr in obj) {
var parent = obj[idStr];
}
You can use JSON object for this purpose, You are confusing the usage of .map() in Jquery with map of other languages.
You can create a Json object like,
var xObj = {};
xObj.id = 'parentElemtnId';
alert(JSON.stringify(xObj)); // { id : 'parentElementId' }
I have an object with a bunch of properties. Some properties are to be displayed in input elements, some in labels.
So, my code looks like this:
var data = getMyData();
var propNames = Object.keys(data);
var i, propName, elem;
for (i = 0; i < propNames.length; ++i) {
propName = propNames[i];
elem = $("#" + propName);
if (elem.is('input')) {
elem.val(data[propName]);
} else {
elem.html(data[propName]);
}
}
Is it the right way to do it in jquery? Cause it looks kinda ugly...
Thanks.
I find it easier to store the method name in a variable (text/val), so that we don't have so much code repetition (the conditional in your code makes for unnecessary repetition).
Also, since you're anyhow using jQuery, you might as well use each. It simplifies all of it into this:
$.each(getMyData(), function (key, val)
{
var el = $("#" + key),
method = el.is('input') ? 'val' : 'text';
el[method](val);
});
Here's the fiddle: http://jsfiddle.net/pFbSf/
If you don't like storing the method name in a variable, use this instead:
$.each(getMyData(), function (key, val)
{
var el = $("#" + key);
el.is('input') ? el.val(val) : el.text(val);
});
Here's the fiddle: http://jsfiddle.net/GQTZv/
If you worry about jQuery not using hasOwnProperty, you can run the check yourself:
var data = getMyData();
$.each(data, function (key, val)
{
if ( ! data.hasOwnProperty(key) ) return;
var el = $("#" + key);
el.is('input') ? el.val(val) : el.text(val);
});
Here's the fiddle: http://jsfiddle.net/GQTZv/1/
I think you can rewrite that for-loop with the jQuery .each() function, which can iterate over any array or object. It takes a callback function, which is given the index (or key) and the value of each item.
In your example it would be something like:
jQuery.each(data, function(key, value) {
elem = jQuery("#" + value);
if (elem.is('input')) {...
Check out the docs for jQuery.each()
Assuming you're trying to fill either an input or a textarea, you should be able to replace this with:
var data = getMyData();
var propNames = Object.keys(data);
for (i = 0; i < propNames.length; ++i) {
$("input#"+propNames[i]).val(data[propNames[i]);
$("textarea#"+propNames[i]).html(data[propNames[i]);
}
You might even get away with replacing the two jQuery selectors with:
$("input#"+propNames[i]).val(data[propNames[i]).html(data[propNames[i]);
Since input elements don't have innerHTML and textarea elements don't have val, this should work as-is. Hackish, but it's succinct.
I don't see how that looks ugly but I don't understand why you need Object.keys... You can simplify it a bit with a regular for...in:
var data = getMyData(),
d, $el;
for (d in data) {
$el = $('#'+ d);
if ($el.is('input')) {
$el.val(data[d]);
} else {
$el.html(data[d]);
}
}
Everything looks fine to me Mark. The one thing I would highly advise against is using a new Object prototype method like Object.keys, which is only available in IE9+ and other newer browsers. Instead either create the prototype for it before all of your JS (something I actually don't like doing) or instead have a replica work-around global function / namespace method that takes care of it like function getkeys() at the bottom.
http://jsfiddle.net/WJ24q/1/
for (i = 0; i < propNames.length; ++i) {
var el = $("#" + propNames[i]),
_d = data[propNames[i]];
// you could also use a simple ternary instead of the if/else
el.is('input') ? el.val(_d) : el.html(_d);
}
Function instead of Object.keys:
function getKeys (obj){
var keys = [];
for(var key in obj){
keys.push(key);
}
return keys;
}
The following code is only assigning the value of the last .enter_form input to the last MYAPP.list[0].responses[MYAPP.score.round].form[key] (where key is the only thing that varies). I think it's because only the last value of the key is being passed to addEntry(), but I can't figure out how to get around that.
$('.enter_form input').each(function() {
var key = $(this).attr('id');
var val = $(this).val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form = [];
function addEntry() {
return function(k) {
MYAPP.list[0].responses[MYAPP.score.round].form[k] = {'entry': userDict[k]};
}(key);
}
addEntry();
}
Your addEntry function is redundant since each iteration is already run inside it´s own scope so key and val are preserved properly (hope that explanation makes sense). Also the array you where inserting into was overwritten each iteration as well, so at the end of the .each() you end up with an array with only 1 value. It should also be an object rather then an array, even if the id's are numerical.
// you where overwriting this each iteration
MYAPP.list[0].responses[MYAPP.score.round].form = {};
$('.enter_form input').each(function() {
var el= $(this); // cache instead of creating a new jQuery object each time
var key = el.attr('id');
var val = el.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {'entry': userDict[key]};
}); // ); was also missing
Should work.
It's a bit hard to work out what it's meant to do, but I think this is probably it:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
$('.enter_form input').each(function() {
var $this = $(this),
key = this.id,
val = $this.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {
'entry': val
};
});
That's based on your saying that "...key is the only thing that varies" (presumably $(this).val() also varies, but I took your point). It will add entries to MYAPP.list[0].responses[MYAPP.score.round].form for each of the form's input ids, as well as adding them to the userDict map.
As a side note, if the id values on the input elements aren't purely numeric, then I suspect you want to start with a blank object:
MYAPP.list[0].responses[MYAPP.score.round].form = {};
// ^^-- change is here
...rather than an empty array:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
...although since arrays are objects, it works even if you're adding non-numeric properties.
Off-topic: No need for $(this).attr('id'). Just use this.id.