Dynamically assign properties to a JS object - javascript

I needed to dynamically add properties to an js Object, which I achieved via eval():
$ ->
#Methods
window.add_address = (attributes, id=new Date().getTime())->
$container = $('ul#addresses_list')
$unit = $('<li>')
$.each attributes, (key,value)->
$input = $('<input type="hidden">')
$input.attr 'name', "contact[addresses_attributes][#{id}][#{key}]"
$input.val value
$unit.append $input
$container.append $unit
#Events
#Add address button
$('a#add_address').on 'click', (ev)->
attributes = new Object
$('#address_fields').find('input').each ->
eval("attributes.#{$(this).attr 'id'}='#{$(this).val()}'");
add_address attributes
This works perfect but I feel awkward with the eval(), is there anyway to do this "prettier"? I mean, I searched for alternatives like the Jquery .serializeArray() but it seems to work only with a queried form and I need to get the inputs from that #address_fields div.

Use object['key'] notation
attributes[$(this).attr('id')] = $(this).val();
It's also very efficient to create object using:
var attributes={};
EDIT: Along similar lines can write the jquery methods in same notation
attributes[$(this)['attr']('id')] = $(this)['val']();

Related

Store jQuery objects in an array/object

I want to create a JS array that contains jQuery objects like this:
var oFormFields = new Object;
oFormFields.label = $(document.createElement('label'));
oFormFields.input = $(document.createElement('input'));
Since this crashes my code, i expect this is not possible. Any alternatives? This is my simplified version, I want to include some other properties so I'm able to re-use this in my code when building dynamic forms.
EDIT: Seemed this did work after all... what I wanted to do, was something like this:
var oFormFields = new Object;
oFormFields.name_field.label = $(document.createElement('label')).addClass('nam_field');
oFormFields.name_field.input = $(document.createElement('input')).addClass('nam_field');
This does break my code. I'm pretty new to jQuery, coming from a PHP background I'm having some troubles adjusting to the correct way to work with arrays / objects.
Just use it like this:
var oFormFields = {
label: $('<label />'),
input: $('<input />')
};
You can create the element directly using jQuery. Furthermore, as mentioned in the comments, you should prefer the object literal notation over the new syntax.
var arr = [];
var oFormFields = {};
oFormFields.label = $('<label/>');
oFormFields.input = $('<input/>');
arr.push(oFormFields);
.........

JQuery - get attr/text from HTML string in a variable

I have a HTML string that I'm passing through a function and I want to be able to perform Jquery methods on that variable from inside the function - such as .attr('href') or .text(). I'm sure there is a simple solution for this and something more elegant then temporarily appending the DOM.
HTML
<div class="here"></div>
Javascript
link = 'Google';
// This works
$('.here').html(link);
works = $('.here').text();
console.log(works);
// This doesn't
not = link.text();
console.log(not);
http://jsfiddle.net/dfgYK/
You need to create a jQuery object from link in order to use jQuery methods on it. Try:
not = $(link).text();
DEMO: http://jsfiddle.net/dfgYK/1/
Depending on what you're doing with link, it might be beneficial to do this earlier in your code so that you can just use something like:
var $link = $(link);
console.log(link.text());
You can make a jQuery object that is not part of the DOM by passing a string in:
link = $('Google');
Then, jQuery methods will work on it:
var text = link.text();
Create the link with jQuery instead:
var link = $('<a />', {
href: "http://www.google.com",
text: "Google"
});
Then you can access it's properties with link.text() like you wanted.

Referencing input in specific form

I'm catching data-async of form created using twitter bootstrap in following manner:
$('form[data-async]').live('submit', function(event) {
var $form = $(this);
var $target = $($form.attr('data-target'));
var target_id = $target[0].id;
....
}
I'd like to reference input with name "username" in the form in question... I tried $form.username, $form['username'], but to no avail, and I couldn't find how to get the input. I know I can use
$('#formid input[name=bla]')
but since I've already got form object, I'd like to use that if possible.
Thanks
You can use .find():
var $input = $form.find('input[name=bla]');
edit — commenter Jack points out that there's also the HTML5 "elements" property of the form DOM element. That lets you get to inputs by name or id, or by numeric index.
var input = this.elements['bla'];
Access by name is complicated by the fact that the mechanism also considers element "id" properties (in fact those take precedence, I think).
Inside your submit handler, the username input field can be referenced simply by:
this.elements['username']
No need for fancy jQuery :)
Update
Didn't realize elements is a fairly recent addition. Before that you could use:
this.username
Update 2
A shimmed version would look like this:
var field = this.elements ? this.elements['username'] : this.username;
You can use the form object as context with selector to find the elements within context.
Syntax: jQuery( selector [ , context ] )
$('input[name=bla]', $form );
You can use this as it represents your form.
$('form[data-async]').live('submit', function(event) {
$('input[name=bla]', this ); // this is your form
})

Adding custom data attribute for a new node in Jquery does not work

I tried to use the method data (jQuery 1.7.1) in this code:
var q = '<div class="form-error-marker"></div>';
var t = $(q).data('message', message).insertAfter(el);
and it does not work.
Note that this works:
var t = $(q).attr('data-message', message).insertAfter(el);
Why does the first variant not work?
EDIT: insertAfter works correctly and new div is added after el (which is instance of one element which I get by getElementById() function; long story short I have a library that I extend).
When I say 'it does not work' I mean that the attribute 'data-message' is not stored.
Using data like that sets an arbitrary piece of data for this node; it doesn't add a new data- attribute. Just add the attribute with the attr function, and then access it with data
var q = $('<div class="form-error-marker"></div>').attr("data-message", message);
Now access it like this:
var message = q.data("message");
Here's a fiddle
When you use jQuery.data you don't change element attributes, instead your data saved in $.cache.
So if you want to change element attributes use jQuery.attr, when you want to save some info use jQuery.data

Hide cached objects in jQuery

I'm not sure if "cached" is a correct term for this one. Maybe I should use "instantiated" instead. However, say I want to "cache" several objects, to save some resources:
var $foo = $("#foo"),
$bar = $("#bar");
Now, if I want to hide them, can I use a one-liner instead of:
$foo.hide();
$bar.hide();
I reckon that this one is quite simple (read: "stupid"), but hey... I can't figure it out all by myself...
You can also use .add() to roll up a bunch of jQuery objects and selectors:
$foo.add( $bar ).add('.someclass').add( $other_objects_or_selectors ).hide();
you can use something like this:
$.each([$foo, $bar], function(i, v) {
v.hide();
});
You can have multiple selectors in jQuery separated with comma:
$("#foo, #bar").hide();
If you're doing this for many id's, maybe do something like:
items = ['foo', 'bar'];
cache = {};
$.each(items, function(i,key) {
cache[key] = $('#' + key);
cache[key].hide();
});
Then later on access the 'cache' like cache['foo'].
Define a class for all these elements and then hide by the class
$('#foo').addClass('toHide');
//Later
$('.toHide').filter(':visible').hide();

Categories