How to apply validation to cloned elements in Jquery? - javascript

There is a textbox with label; having validation of isnumeric.
Money: <input type="text" id="dollar" name="dollar" data-require-numeric="true" value="">
//Textbox with id dollar0
At run time, I have created clone of above; by clicking on button named add; and this created another textbox with different id and other attributes same; say.
Money: <input type="text" id="dollar1" name="dollar1" data-require-numeric="true" value="">
//Cloned textbox; cloned by clicking on a button named clone
On both textboxes data-require-numeric is true.
Issue: For default textbox the JQuery validation is getting executed. But for new clone; JQuery is not running.
Following is jquery:
var economy= {
init: function () {
$('input[type="text"][data-require-numeric]').on("change keyup paste", function () {
check isnumeric; if yes then border red
});
}};
$(economy.init);
How to resolve this?

Try this : You need to register click event handler using .on() in following way where registering the click handler for document which will delegate the event to 'input[type="text"][data-require-numeric]'. This way you can handle events for dynamically added elements.
var economy= {
init: function () {
$(document).on("change keyup paste",'input[type="text"][data-require-numeric]',
function () {
check isnumeric; if yes then border red
});
}};
$(economy.init);

to bind change event on dynamic dom elements . use class reference instead of id . And bind the event to its parent like,
$(document).ready(function(){
$(".parent").on("keyup",".dynamicdom",function(e){
value = $(e.target).val()
//then do your validation here. and you can attach multiple events to it
})
})
<div class="parent">
<input type="text" class="dynamicdom" >
<input type="text" class="dynamicdom" >
</div>

Related

DOM equivalent to jQuery `.detach()`?

I’m trying to remove an input field by clicking an “X button”. After it is removed it will not post its value when the form is submitted. A “+ button” appears that allows the user to add said input again. The input has an onclick event that opens a calendar and after reattaching, the calendar does not open on click anymore. I can’t use jQuery.
adderBtn.onclick = function (e) {
var elem = that.hiddenElems.shift();
that.collectionItemContainer.append(elem);
}
removerBtn.onclick = function (e) {
collectionItemElem.remove();
that.hiddenElems.push(collectionItemElem);
}
The question is how do I remove and reattach DOM nodes without losing the Events.
When you remove an element, as long as you keep a reference to it, you can put it back. So:
var input = /*...code to get the input element*/;
input.parentNode.removeChild(input); // Or on modern browsers: `input.remove();`
later if you want to put it back
someParentElement.appendChild(input);
Unlike jQuery, the DOM doesn't distinguish between "remove" and "detach" — the DOM operation is always the equivalent of "detach," meaning if you add the element back, it still has its handlers:
Live Example:
var input = document.querySelector("input[type=text]");
input.addEventListener("input", function() {
console.log("input event: " + this.value);
});
input.focus();
var parent = input.parentNode;
document.querySelector("input[type=button]").addEventListener("click", function() {
if (input.parentNode) {
// Remove it
parent.removeChild(input);
} else {
// Put it back
parent.appendChild(input);
}
});
<form>
<div>
Type in the input to see events from it
</div>
<label>
Input:
<input type="text">
</label>
<div>
<input type="button" value="Toggle Field">
</div>
</form>
If you remove the element without keeping any reference to it, it is eligible for garbage collection, as are any handlers attached to it (provided nothing else refers to them, and ignoring some historic IE bugs in that regard...).
To detach an element in function form:
function detatch(elem) {
return elem.parentElement.removeChild(elem);
}
This will return the 'detached' element

Javascript click event firing twice, even with stopPropagation

I have a set of items like this:
<label for="Cadenza-1" class="cars">
<input type="checkbox" value="1" alt="Cadenza" id="Cadenza-1" name="vehicles[]">
<img src="img/bill_murray_173x173.jpg">
<span>Cadenza</span>
</label>
there's about 13 of them. I want to add a class to the label when clicked. However, the click event fires twice. right now I'm debugging the click event then I'll add the class:
var cars = document.getElementsByClassName('cars');
for(var c = 0;c < cars.length; c++){
cars[c].addEventListener("click", function(e){
selectVehicle(cars[c],e);
},false);
}
function selectVehicle(el,e) {
console.log(e);
e.stopPropagation();
}
The console.log fires twice.
Try adding preventDefault after your stopPropogation:
function selectVehicle(el,e) {
console.log(e);
e.stopPropagation();
e.preventDefault();
}
I believe it is best to place console.log(e) after the stopPropogation & preventDefault though. You will also then need to implement functionality to set the checkbox to checked since this would prevent that from happening.
When the <span> or the <img> receives a "click" event, that'll bubble up the DOM to the <label> element, and your event handler will be called. The <label> then triggers another "click" event on the <input> element, and that also bubbles up to the <label>.
You can check in the handler to see whether the <input> was clicked:
function selectVehicle(el,e) {
if (e.target.tagName !== "INPUT") return;
// do stuff
}
Alternatively, you could just add the "click" handler only to the <input> itself.
Now you're also going to notice that your code isn't working because you've hit a common problem with binding event handlers inside loops. The problem is that the variable c will have as its value the length of the cars list by the time the event handlers actually run. There are a few ways of dealing with that; one is to loop with forEach() instead of a for loop:
[].forEach.call(cars, function(car) {
car.addEventListener("click", function(e){
selectVehicle(car,e);
}, false);
});
You are adding the event listener to the label, you should add the event listener to the checkbox because the label behavior copy the same of the input assigned in for.
Please note that if you click just in the checkbox the callbacks works fine, this is because the event on the label is raised by the checkbox.
The right way to do that is to add the event listener only for the checkbox or adding prevent default in the setlectVehicle callback.
You are not required to preventDefault or stopPropagation, but just to add listner on the input element.
cars[c].children[0].addEventListener("click", function(e) {
Try this. It is working as expected.
Additionally, you are not required to use Id's with label's for if the label element encloses the required input/other elements
var cars = document.getElementsByClassName('cars');
for (var c = 0; c < cars.length; c++) {
cars[c].children[0].addEventListener("click", function(e) {
selectVehicle(cars[c], e);
}, false);
}
function selectVehicle(el, e) {
console.log(e);
}
<label class="cars">
<input type="checkbox" value="1" alt="Cadenza" name="vehicles[]">
<img src="img/bill_murray_173x173.jpg">
<span>Cadenza</span>
</label>
<label class="cars">
<input type="checkbox" value="1" alt="Cadenza" name="vehicles[]">
<img src="img/bill_murray_173x173.jpg">
<span>Cadenza 2</span>
</label>

keyup function for multipe input fields in jquery

Ok i have keyup for multiple input fileds, my problem is because i have two calls, and i want only one. So when code is inserted only one action happens.
$(":input").keyup(function() {
if(is_draft_started == 0) {
s2 = setInterval('draft("' + frm_name + '")', auto_save_time);
is_draft_started = 1;
}
});
but with this selector when key is pressed, my function draft is called twice because i have two input fields, is there any solution, to works this only once, so when i press button one, one call exists?
No matter that you have two input fields, only one of these will trigger an event. So I guess that you have some other problems, e.g. attaching the same handler for the field twice. E.g.:
HTML:
First input: <input type="text"></input><br/>
Second input: <input type="text"></input><br/>
Total number of calls: <span id="function_calls">0</span>
JS:
var funcCalls = 0;
$(":input").keyup(function() {
$('#function_calls').text(++funcCalls);
});
Fiddle.
You can use ID or Classes to specify which input should trigger your function. Example:
<input type="text" class="trigger"></input>
<input type="text" class="no_trigger"></input>
<input type="text" class="trigger"></input>
Function will be applyied to all inputs with trigger class
$('input.trigger').keyup(function(){
alert("called just once");
});
check out this demo

How to make One Jquery script work for multiple inputs with slightly different name

I have a jquery keyup script that changes a data-attribute for a checkbox input when a text input value is changed. Currently it works for only one instance of a checkbox input and text input. However, I need to modify the script to work for 10 instances.
In this fiddle you can see that I have it working for the first instance number 1, but not for 2-10.
So for example, the script is triggered when a user changes the value of the input with the id="account_balance1" as seen below.
<input type="checkbox" checked="checked" data-cost="100" debt="" value="" name="f_2[]"/>
This is the input where the value is entered for the keyup event
<input type="text" maxlength="7" class="balance" id="account_balance1" name="cardbalance" value=""/>
But I need it to work for 10 instances of these two inputs; for each instance there is an li id=card_" and input id="account_balance_" that increase 1 increment, like this... li id="card_1" to li id="card_2" to li id="card_3" and so on. This is same for the input id="account_balance_1, it goes to _2 to _3 and so on.
This is the keyup script
$(function () {
$('#account_balance1').on('keyup blur paste', function() {
var self = this;
setTimeout(function() {
var str = $(self).val();
$("input[data-cost][debt]").data('cost',str.replace(/^\$/, ''));
$("input[data-cost][debt]").data('debt',str.replace(/^\$/, ''));
$('#jquery-order-form').data('jprice').onChange();
}, 0)
})
});
Just change your jquery selector:
Instead of this:
$('#account_balance_1').on('keyup blur paste', function() {
do this:
$('.balance').on('keyup blur paste', function() {
This works because all your involved inputs have the class balance.
Fiddle here: http://jsfiddle.net/edgarinvillegas/8jdfJ/10/
Cheers
See this
http://api.jquery.com/attribute-starts-with-selector/
You just need to use this selector for selecting appropriate elements
$('[id^=account_balance_').on('keyup blur paste', function() {...

using .wrapInner instead of .show()

newbie here. I am trying to used jquery wrapInner to show the next choice for the user while trying to hide the original element. Here is my jsfiddle.
Once I click endorse radio button it hide the elements in between . The cancel button show the elements back. But clicking endorse radio button again nothing happen.
Any help on this would be more than appreciated !
html:
<div id="engr-action" >
<div id="engr-choice">
<input id="endorse" class="engr-choice" type="radio" name="encoder-pick"/>
<label for="endorse">ENDORSEMENT</label>
<input id="encode" class="engr-choice" type="radio" name="encoder-pick"/>
<label for="encode">ENCODE</label>
</div>
<button id="cancel-action">Cancel</button>
</div>
jquery:
$(function(){
$('#engr-choice').buttonset();
$('#cancel-action')
.button()
.click(function() {
$('#engr-choice').html('');
$('#endorse-edit').hide();
$('#engr-choice').wrapInner('<input id="endorse" class="engr-choice" type="radio" name="encoder-pick"/><label for="endorse">ENDORSEMENT</label>');
$('#engr-choice input').removeAttr('checked');
$('#engr-choice').buttonset('refresh');
return false;
});
$('#endorse').click(function(){
$('#engr-choice').html('');
$('#engr-choice').wrapInner('<div id="endorse-edit">Edit</div>');
$('#endorse-edit').button();
return false;
});
});
Since your element is generated "on the fly", thru javascript, your $('#endorse').click(.. event wont work as that element did not exist on DOM, so in order to add events to your elements, created on the fly, you would need to use event delegation, so
change:
$('#endorse').click(function(){
..
to
$(document).on('click', '#endorse',function(){
...
See:: Updated jsFiddle
You can try this: Fiddle setup
$(function () {
$('#engr-choice').buttonset();
$('#cancel-action').button().click(function () {
$('#engr-choice').html('');
$('#endorse-edit').hide();
$('#engr-choice').append('<input id="endorse" class="engr-choice" type="radio" name="encoder-pick"/> <label for="endorse">ENDORSEMENT</label>');
$('#engr-choice input').prop('checked', false);
return false;
});
$('#engr-action').on('click', '#endorse', function () {
$('#engr-choice').html('');
$('#engr-choice').wrapInner('<div id="endorse-edit">Edit</div>');
$('#endorse-edit').button();
});
});
As you are putting html elements via javascript/jQuery so direct binding of events won't be available for them, so you need to do it via event delegation that is to delegate the event to the static closest parent which is in your case is #engr-action or you can do it with $(document) which is always available to delegate the events.

Categories

Resources