datepicker added dynamically won't work - javascript

I have detected a problem with datepicker. I'm adding controls dinamically, and one of them is a datepicker, along side a couple of selects and a textarea.
Well, whenever i add a datepicker, lets say i have 3 datepickers, i set the date of the first, then i try to set the date of either the second or third, well, my problem is that setting the date of the second or third sets it to the first one
Refer to this fiddle to see the problem reproduced. Just add 2 or 3 datepicker clicking the add button and try to set the dates. Any idea on why is this and how can it be solved will be pretty much appreciated

That's because you are using the same ID when you clone the element, if you are using the same ID there is no way for the JavaScript to differentiate between them.
If you switch the IDs to classes it will work, see here: http://jsfiddle.net/j72UG/2/
HTML
<input type='button' value="add" id="addLi" />
<ul class="list">
<li class="dateLi">
<input type='text' class='date' />
</li>
</ul>
JS
var liClone;
$(function () {
liClone = $(".dateLi").clone(true);
$(".dateLi").remove();
$("#addLi").click(function () {
var clonado = liClone.clone(true);
clonado.appendTo(".list");
clonado.find("input").datepicker();
});
});

When you're cloning, all your elements retain the same ID. In a given DOM structure, only one (1) element can have a specific ID at any given time. So give your list items a class or an ID ending with a serial instead, in order to avoid this problem in the future.
var li = $('<li class="dateLi"><input type="text" /></li>');
See this updated jsfiddle.

that's because you have to change the id of each input and li.
try this:
jsfiddle.net/LgRR7/

Related

Create unique buttons dynamically

I'm new to jQuery and am trying to create jQuery UI buttons dynamically and them to a list. I can create one list item but no more are appended after it. What am I doing wrong?
$('#buttonList').append('<li><button>'+ username + '</button>')
.button()
.data('type', userType)
.click(function(e) { alert($(this).data('type')); })
.append('<button>Edit</button></li>');
<div>
<ul id="buttonList">
</ul>
</div>
This only creates one list item with two buttons (although the second button seems to be encased in the first one, but I can probably figure that issue out). How do I get it to create multiple list items with their own unique 'data' values (i.e. I can't do a find() on a particular button class and give it data values as all buttons would then have the same data)?
I suggest to exchange the position of what you are appending and where you are appending to. This way, you retain the appended object, and should be able to work with it as a standard jQuery selector. From your code i commented out the .button() and the .append() lines, because i'm not sure what you want to do with them. Should you need help adding those lines, just drop a comment to my answer ;)
Oh, i almost forgot: i use var i to simulate different contents for username and userType data.
A JSFiddle for you is here: http://jsfiddle.net/cRjh9/1/
Example code (html part):
<div>
<p id="addButton">add button</p>
<ul id="buttonList">
</ul>
</div>
Example code (js part):
var i = 0;
$('#addButton').on('click', function()
{
$('<li><button class="itemButton">'+ 'username' + i + '</button></li>').appendTo('#buttonList')
//.button()
.find('.itemButton')
.data('type', 'userType'+i)
.click(function(e) { alert($(this).data('type'));
})
//.append('<button>Edit</button></li>')
;
i++;
});
You need complete tags when you wrap any html in a method argument. You can't treat the DOM like a text editor and append a start tag, append some more tags and then append the end tag.
Anything insterted into the DOM has to be complete and valid html.
You are also not understanding the context of what is returned from append(). It is not the element(s) within the arguments it is the element collection you are appending to. You are calling button() on the whole <UL>.
I suggest you get a better understanding of jQuery before trying to chain so many methods together
Just a very simplistic approach that you can modify - FIDDLE.
I haven't added the data attributes, nor the click function (I'm not really sure I like the
inline "click" functions - I generally do them in jQuery and try to figure out how to make
the code efficient. Probably not very rational, but I'm often so).
JS
var names = ['Washington', 'Adams', 'Jefferson', 'Lincoln', 'Roosevelt'];
for( r=0; r < names.length; r++ )
{
$('#buttonList').append('<li><button>'+ names[r] + '</button></li>');
}
$('#buttonList').append('<li><button>Edit</button></li>');

which getElement function to click button?

Trying to figure out how to click this button
<input class="button" type="submit" name="checkout" value="Check out">
by using this function
document.getElementBy????('????').click()
or should another function be used?
You can use document.getElementsByName('checkout')[0].click()
You can also use document.getElementsByClassName('button')[0].click()
You can add an id in the input and use dcoument.getElementById or you can use document.getElementsByClassName which'll return you an array.
document.getElementsByClassName('classname')[0].click()
Use this for javascript
document.getElementById("nameofid");
Add an id on your element in the dom and add onclick="(javascript here)" attribute
<input class="button" type="submit" id="nameofid" name="checkout" value="Check out">
Add a function in the javascript to be called by the button using onclick attribute
function myfunction(){
var myvar = document.getElementById("nameofid");
//you may adjust its properties by calling myvar.nameofproperty
//or even call a method myvar.nameofmethod
}
First of all, to be very sure, you should just give your button a unique ID:
<input id="myCheckoutButton" class="button" name="checkout" value="Check out" />
document.getElementById("myCheckoutButton").click();
Basically for your problem and assuming you cannot modify html for some sinister reason...
document.getElementsByName
Would be your choice, howver this works only if you are 100% sure that there is only one element with this name on your document. If its not, it is a little bit tricky but works aswell:
for(var i = 0; i < document.getElementsByName("checkout").length; i++) {
if(document.getElementsByName("checkout")[i].value == "Check out") {
document.getElementsByName("checkout")[i].trigger("click");
}
}
But the very-best option if you are able to implement and use jQuery in your page:
By name:
$(".checkout[name=checkout]").trigger("click");
Or by class and comparing value if you have multiple elements:
$(".checkout").each(function() {
if($(this).val() == "Check out")) {
$(this).trigger("click");
return false;
}
}
There are several. The choice comes down to how specific do you want and/or need to be.
Most specific is getElementById() which will require you to have an id on the element. You can only have one on the page and is very specific.
If you have more than on component on the page and want to attach an event to each one the what you want is to use getElementsByClass() which will return an array of all the elements that have that class.
Finally, if you want to reference form elements you can use the name attribute to manage checkboxes and radio elements. It helps lower the specificity of using a unique id without having to add extra classes to every form element: getElementsByName() which (like getElementsByClass() returns an array of elements. Managing the difference between text inputs and checkbox inputs however is a topic for another question.

Exclude Element from .html()

I have to remove a specific element (button with #add_phone) from .html() of jquery.
So here's the thing. At first there are field(phone number) + select(phone type) + button(#add_phone), and all three are enclosed in div as a container. And when I click the button, it will recreate that through .html().
The JS is as follows:
$('#add_phone').click(function() {
$('div.multiple_number:last').after('<div id="phone_div_id' + phone_div_id + '" class="multiple_number">'+ $('div.multiple_number').html() +'</div>');
...
//append a remove [-] button, etc...
});
and here's the html:
<div class="multiple_number" id="phone_div_id0">
<label>Phone Number(s):</label>
<input name="phone" id="phone[]" placeholder="Phone Number"/>
<select name="phone_type[]" id="phone_type">
<option value="1">Mobile</option>
<option value="2">Home</option>
<option Value="3">Office</option>
<option Value="3">Fax</option>
</select>
<input type="button" name="add_phone" class="add_phone_class" id="add_phone" value="ADD MORE" />
</div>
So in effect, I am creating multiple phone numbers for a form. But, here's the problem. Inside is an input type="button" (#add_phone button). And I would want to exclude it from .html().
I have tried:
$('div.multiple_number:not(#add_phone)').html()
$('div.multiple_number:not(input#add_phone)').html()
$('div.multiple_number:not(#add_phone)').not(#add_phone).html()
$('div.multiple_number:not(#add_phone)').not(input#add_phone).html()
And the class name counterpart instead of using id name. I wouldn't also want to place the #add_phone button outside the div, for aesthetics reason.
I'm a little bit unclear about what you're looking for, but I assume that when the #add_phone button is clicked, you want the form to be duplicated and added below it with the exception of the #add_phone button itself.
Working off that assumption, the following should work
$('#add_phone').click(function() {
var numberForms = $('div.multiple_number');
var newNumberForm = numberForms.eq(0).clone(true);
newNumberForm.find('#add_phone').remove();
newNumberForm.attr('id', 'phone_div_id' + numberForms.length);
numberForms.last().after(newNumberForm);
});
Here's a live jsfiddle demo to show it working.
Your initial attempts didn't work for a few reasons. The main one being that :not() selector and .not() methods only operate on the element being selected. It doesn't filter based on child elements. Those methods would only work if the element you were selecting <div class="multiple_number" /> also had the ID add_phone.
Also, it is not recommended to use .html() as a way of cloning methods. Using string manipulation as an alternative to direct DOM manipulation can cause problems later on. Using .html() will force you to have to re-bind event handlers to the newly created DOM elements. The strategy I've provided above should be more future-proof, since it will also clone event handlers for any elements being copied. There are also cases where certain browsers will not replicate the original elements exactly when calling .html(), which is another reason to avoid it unless you have a specific reason for serializing your DOM elements as a string.
Try this instead :
var innerHTML = $("div.multiple_number").html()
.replace($("div.multiple_number input#add_phone").html(), "");
Good Luck

toggleClass() on Parent not working even though the parent is being found

Hi I have the following HTML repeated in my page (obviously the names, for and id attributes change in each instance):
<div class="funkyCheckBox">
<label for="uniqueName"> Whatever Text </label>
<input type="checkbox" name="uniqueName" id="uniqueName" />
</div>
What this does with some CSS is make the give the appearance of a big button, the input is hidden and I add a class to the div depending on the checked value of the input. I use the following JavaScript /jQuery for this
$(".funkyCheckBox").live("click, tap", function(event){
$(this).toggleClass("funkyCheckBoxActive");
var nextCheckBox = $(this).find("input[type=checkbox]");
nextCheckBox.prop("checked", !nextCheckBox.prop("checked"));
});
Now this was all fine and good but during testing I noticed that if you click on the label text the class was not applied and the value of the input isn't toggled... thus I added the following...
$(".funkyCheckBox label").live("click, tap", function(event){
$(this).parent("div").toggleClass("funkyCheckBoxActive");
var nextCheckBox = $(this).next("input[type=checkbox]");
nextCheckBox.prop("checked", !nextCheckBox.prop("checked"));
});
Now this is great as clicking the label text now changes the value of the input however the parent DIV is not taking / toggling the "funkyCheckBoxActive" class. I am unsure why is as I then used console.log($(this).parent("div")) within the callback function and I am outputting the attributes of th dom object. Does anyone know why my toggleClass is not being applied?
Depending on the version of jQuery, your code will work or not.
Note that the browser is already toggling the checkbox when you click on a label that references it; so you would only need to do this:
$('#uniqueName').change(function() {
$(this).parents("div").toggleClass("funkyCheckBoxActive");
});
please use the "on" method instead of "live" as it is deprecated. also the "for" attribute in LABEL Tag points to an existing Id.
here is the corrected and working code:
<div class="funkyCheckBox">
<label for="uniqueName"> Whatever Text </label>
<input type="checkbox" name="uniqueName" id="uniqueName" />
</div>
and
$(".funkyCheckBox label").click(function(event){
$(this).parent("div").toggleClass("funkyCheckBoxActive");
var nextCheckBox = $(this).next("input[type=checkbox]");
var nextCheckBoxValue = nextCheckBox.val();
nextCheckBox.val(! nextCheckBoxValue);
}); ​
​
EDIT: here is the jsFiddle link
http://jsfiddle.net/RUYWT/
EDIT2: #Mike Sav: I have revised your code and it's working now with all possible cases:
http://jsfiddle.net/RUYWT/11/

What javascript method to target descendants?

I'm using a javascript function to set the value of a text field, based on the option chosen from a select field.
The javascript contains a lot of other stuff, but only the following is relevant to this question.
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next('.target')[0];
----other stuff----
});
});
I originally had my form set up as follows, and everything worked fine.
<select class="source"></select>
<input class="target"></input>
I've subsequently added some styling, which has required extra divs.
<select class="source"></select>
<div class="level1">
<div class="level2">
<input class="target"></input>
</div>
</div>
Now the javascript function does not work, because the next method only targets siblings and not descendants.
So my question is, what method should I be using to target a specific descendant?
An important fact: this markup is part of a nested form, and is repeated several times on the same page. It is important that the function targets the correct .target field, i.e. immediately subsequent and descendant.
I've tried obvious candidates – .find(), .children() — but these don't seem to work. Would appreciate any ideas or pointers.
Thanks!
Now that in the new markup structure .target input is wrapped in a div with class level1 you can find that div first using next() and then use find() method to get to the .target input.
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next('.level1').find('.target')[0];
----other stuff----
});
});
Note: Even if you don't pass any selector to next() also it will work fine because it only selects the immediate next sibling optionally filtered by the selector which we pass.
In your case this would work:
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next().find('.target')[0];
----other stuff----
});
})
;
It's a descendant of the sibling, so this should do the trick:
var target = $(this).next('.level1').find('.target')[0];

Categories