jQuery: Running multiple datepicker's on dynamically created inputs - javascript

I am trying and failing to add datepicker to inputs that are created dynamically.
They have different id's and I am specifically targeting the new input and calling datepicker.
In the jsFiddle example below it only works for the 2nd input (first one datepicker is called on) and does not work for any others after that.
Here is the jsFiddle: http://jsfiddle.net/TJfbc/1/ Press the plus sign to add more.
Note: I am aware the first element will not have the datepicker.

Here's a cleaner alternative
$(function() {
//append one handler to the parent to detect append actions
$('.action_items').on('click', '.expand', function() {
var $el = $(this);
$el.parent()
.clone()
.appendTo($el.closest('.action_items'))
.find('input')
.removeClass('hasDatepicker')
.each(function () {
newName = this.name.slice(0,6) + (parseInt(this.name.slice(6)) + 1);
this.name = newName;
this.id = newName;
})
.datepicker();
//change text, remove original handler, add the remove handler
$el.text('-').off('click').on('click',function(){
$(this).parent().remove();
});
})
});​

http://jsfiddle.net/TJfbc/27/
You need to "refresh" the previous textfield that has already class of 'hasDatepicker' before you can initialize a new one
new_action_item.find('.dpDate').removeClass('hasDatepicker').datepicker()
An improvement on readability:
No need to repeatedly call $() on new_action_item since clone() returns an already jQuery object

Related

Chosen JS with clone(true,true), rerender on append

I am using the Chosen JS jQuery plugin & I am trying to get it to rerender every time a cloned element (using true, ture - this is because I need to copy the on click events) is appended to the dom.
This is my code:
var container = jQuery(self.options.parent_class + ' tbody tr:first-child'),
container_clone = container.clone(true,true);
var elem = container_clone.find('select');
elem.chosen('destroy');
elem.chosen();
return container_clone;
Here it is on fiddle: http://jsfiddle.net/udj7t/1/
Try this,
$(document).ready(function(){
$('select').chosen();
$('a#clone_me').on('click', function(){
var $clone = jQuery('#toClone select:first').clone();
$clone.removeAttr('style');
//$clone.chosen('destroy');
jQuery('#toClone').append($clone);
jQuery('#toClone select:last').chosen();
});
});
Demo
For those interested in a possible solution that will work with clone(true, true), as per the OP's actual question I found that doing the following worked for me. I also had multiple selects in my cloned row so I needed to use the each() method. This could easily be adapted though.
// Look through the cloned row and find each select
$clone.find('select').each(function (){
// Because chosen is a bitch with deep cloned events
// We need to make another internal clone with no events
$clonedChosen = $(this).clone().off();
// Now we can delete the original select box
// AND delete the chosen elements and events
// THEN add the new raw select box back to the TD
$parentTd = $(this).closest('td');
$parentTd.empty().append($($clonedChosen).show());
// Finally, we can initialize this new chosen select
$parentTd.find('select').chosen();
}

Not able to add datepicker to new element

I'm dynamically adding new form elements using jquery. For some reason, a call to .datepicker() won't work on the new elements I add, but did work on the old ones that were not added dynamically. If I put .attr('style', 'color: red;')
instead of .datepicker(), it works. Note that the original call inside of the document ready function works.
This is the code that gets called when the add button is clicked:
function addMulti(name) {
it = $('[name=' + name + ']');
base = it.data('baseName');
on = it.data('number') + 1;
name = base + "-" + on;
copy = it.clone()
copy.prop("name", name).attr("data-is-default", false).removeAttr('data-number').
fadeIn('slow').appendTo(it.parent());
it.data('number', on);
if(it.hasClass('date-pickable')) { // <-- This returns true, I checked.
copy.datepicker();
// Where if I add clone.attr('style', 'color: red;') it turns it red.
}
}
This is the call that makes all of the fields that are created at that point date pickers:
<script type="text/javascript">
$(document).ready(function() {
$("input.date-pickable").datepicker()
});
</script>
There are no errors that show up in firebug or the google chrome "inspect element" thing. Something odd is happening though. If I type in the same call as in the document.ready function into the firebug consul, it still won't make the newly added elements datepickers. Yet if I hover over the output, it selects the elements that it should be targeting.
$("input.date-pickable").datepicker() // What I typed in
Object[input#dp1371953134342.field-input 06/22/2013, input#dp1371953134343.field-input, input#dp1371953134342.field-input 06/22/2013, input#dp1371953134342.field-input 06/22/2013] // What it put out. The last three numbers are the IDs JQuery assigned to the added elements. I checked.
jQuery UI's datepicker will always add the class hasDatepicker to any element that has a datepicker to avoid attaching multiple datepickers to the same element.
When you're cloning an element that already has a datepicker, you get that class as well, and you can't attach a new datepicker to the clone, as jQuery UI thinks the element already has a datepicker.
Remove the class from the clone:
var copy = it.clone(false);
copy.removeClass('hasDatepicker').prop("name", name)
.attr("data-is-default", "false").removeAttr('data-number')
.fadeIn('slow').appendTo(it.parent());
and try not to make all your variables global.
Will this work?
<script type="text/javascript">
$(document).ready(function() {
$(document).on('focus',"input.date-pickable", function(){
$(this).datepicker();
});
});
</script>
Demo JSfiddle

Deleting <li> issue

I'm building a recipe saving application where I have a form that looks like this http://jsfiddle.net/LHPbh/.
As you can see, I have a set of form elements contained in an <li>. You can click Add Ingredient and have more li's added to the field.
My problem is:
The first li is the only one that deletes. If you click Add Ingredient, and then try and delete that one, nothing works?
Is there a way to not have the first li have a delete by it, but all subsequent li's have a delete link on the side? (Just because there should always be at least one ingredient?)
When you call clone(), it isn't duplicating the events. You need to call clone(true) in order for it to do this, as explained in the documentation.
You did not put an event listener on the cloned elements. Also, you should not give the "delete"-link its own id, as those need to be unique.
To make the first ingredient have no delete button, just don't include one in your markup but only dynamically create and append them to the cloned elements:
var deleteButton = $("<a class='float-left'>Delete</a>").click(deleteThis);
$('ul#listadd > li:first')
.clone()
.attr('name', 'ingredient' + newNum)
.append(deleteButton)
.appendTo('ul#listadd');
function deleteThis() {
var li = $(this).closest('li')
li.fadeOut('slow', function() { li.remove(); });
}
Demo at jsfiddle.net
http://jsfiddle.net/LHPbh/2/
$('.deleteThis').live("click", function () {
var li = $(this).closest('li')
li.fadeOut('slow', function() { li.remove(); });
});
It is answer to the 1. point. The problem was, that the eventhandler binding did not happen in newly created elements, because this code runs only on the load of the page. This can be solved by using .live(). And an other problem was, that id-s must be unique. So instead id, here you can use class .deleteThis.
http://jsfiddle.net/LHPbh/19/
This has added answer to the 2. point:
if ($("#listadd li").length == 1) {
return;
}
If the list only contains 1 li element the rest of the callback will not run.
You are adding items that are added to the DOM dynamically, thus jQuery can't access them :)
In this case you can use the following code:
$(document).on('click', '.selector', function(e) {
//code here
});
Secondly, you were loading a quite old version of jQuery.
Thirdly, you were trying to select an element with an ID that already existed, and ID's can only exist one time. I've changed it to a class in the updated example.
Lastly, you were defining the class of the link twice like this:
<a class='float-left' id="deletethis" href='#' class="deletethis">Delete</a>
That also gave a problem, so I changed it to correct markup like this:
<a class='float-left deletethis' href='#'>Delete</a>
Good luck :) I've updated your jsFiddle here:
http://jsfiddle.net/q4pf6/

jQuery .live('click', function() {}); doesn't work for iPad

I have some jQuery functions which update some numbers when new values are selected in a <SELECT> field. The <SELECT> items are added dynamically by the user, so these functions use the .live() function. Everything goes as planned in Mozilla, Chrome, and IE8, but when I try to access the page on my iPad the numbers are no longer being updated accordingly. I have to click the <SELECT> field a second time for the numbers to update. Here is one of my functions:
// Update subtotal when .months is changed
$(".months").live('click',function(){
var pid = this.id.replace("months", "");
var price = document.getElementById('row' + pid).className;
updateSubtotal(pid, price);
});
All of the functions are contained within the document.ready() block. I've tried 'click change' and just 'change' as well, but they have issues in some other browsers.
Thanks for any and all help!
iPad and select elements don't play very nice. You will need to bind to blur if you need the selected value to do anything.
Try something like this ( .months should be your select element ):
// Update subtotal when .months is changed
$(".months").on('blur', function(){
var pid = this.id.replace("months", "");
var price = document.getElementById('row' + pid).className;
updateSubtotal(pid, price);
});
EDIT
Try this:
// Update subtotal when .months is changed
$(document).on('blur|click', ".months", function(){
var pid = this.id.replace("months", "");
var price = document.getElementById('row' + pid).className;
updateSubtotal(pid, price);
});
The nice thing about on() is that you can attach it to an element and delegate from there. Since your $(document) will always be there it can also catch elements you add dynamically to the page and which are not there from the beginning. Since your original code used live I
expect the element to by loaded or generated dynamically. In that case in order to bind an event to it using on() you have to bind to the document and delegate to whatever .months is coming.
If you add an empty onclick="" to the div (or span, or anything), it works....
I dont't know why :)

getting individual atrributes while selecting a class with JQuery

I'm new to javascript and JQuery, and I'm working in a small project with JSP.
I create a grid dynamically with JSP and I added some buttons wich class is "select" and in the alt attribute I set the current row index. That works perfectly, I'm trying to set the onclick dynamically. This is my code
$('.select').click(function (){
alert($('.select').attr('alt'));
}
I want to each button to show its own index, but that code shows just the first index in each button. I've searched how to do it, but nothing comes out.
Is there a chance to do what I want?
change this line as:
alert($(this).attr('alt'));
When jQuery calls your event handler it sets this to be the DOM element in question, so try this:
$('.select').click(function (){
alert($(this).attr('alt'));
});
If you need to access DOM element properties you can then get them directly, e.g.:
alert( this.id );
this.value = "test";
If you need to use jQuery methods on the element you need to pass it to the jQuery function first, e.g.:
$(this).hide();
$(this).css("color","red").slideDown();
$('.select').click(function (){
alert($(this).attr('alt'));
});
Change
alert($('.select').attr('alt'));
by
alert($(this).attr('alt'));
Now you select the attr alt of the button lauch the event.
Not sure if that's what you're looking for but...
$('.select').click(function() {
$('.select').each(function() {
$(this).attr('value', $(this).attr('alt'));
});
});
This'll have every button "show" the value stored within their alt attribute when you click one button.
By the way, if you're using 1 button per row, you'd probably better go with index().

Categories

Resources