.focus() doesn't work on cloned object? - javascript

Hope you are all doing well!
So I have a form that contains list of input text in a row. the form can contains as many rows as possible as there is an 'add row' button that allows user to add dynamically
I use clone() to this 'add row' function and it's working perfectly
Next,each input in a row can only be edited if the corresponding checkbox is checked
I have put the code to the fiddle: FIDDLE DEMO
Now, when the checkbox is checked, we directly put the focus to the first input (which I defined the input class ='first'), once this input is filled, it directly focuses to the next input. and it's working fine, EXCEPT: if I add new row, the focus function doesn't work anymore.
My focus function is:
$("input").keyup(function (event) {
if ($(this).val() != "") {
$(this).next('input').focus();
if ($(this).next('input[type="text"]').val() == "X") {
$(this).closest('.me').find('input').focus();
}
}
});
Is that supposed to be that way? Or is there anything I need to add to the script?
Thanks!!

Use clone(true) instead of clone()
Code
var new_line = $('#content div.2dtme:last').clone(true).append();
DEMO
OR
You need to use Event Delegation. You have to use .on() using delegated-events approach.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.
i.e.
$(document).on('event','selector',callback_function)
Example
$('form').on('keyup', 'input', function (event) {
//Your code
});
instead of
$("input").keyup(function (event) {
//Your code
});
DEMO

Related

Change event to check change on any form element

I have a from with disabled button, which gets enabled when the form is valid. With the function below I'm checking for changes and it works if the form consists only of inputs. How can I check for change on other elements like select or checkbox?
$("#create-rule-form").parsley();
$('input').on('keyup', function() {
$("#create-rule-form").parsley().validate();
if ($("#create-rule-form").parsley().isValid()) {
$('#create-rule-btn').prop('disabled', false);
} else {
$('#create-rule-btn').prop('disabled', 'disabled');
}
});
Use jQuery's :input selector, it matches all tags that are used for form input.
$(":input").on('edit change').function() {
// code here
});
You can use $('form').find('*') to select all of the form's children and grandchildren, and then apply the event to all of them like below.
Also, on a side note, I believe the event you should handle is change instead of keyup, as keyup will not work with checkboxes and dropdowns.
$('form').find('*').on('change', function() {
//do stuff
});

.on('change' ...) doesn't trigger for data changed by JS

I am trying to trigger an event when an input textbox changed:
$('.packeta-selector-branch-id').on('change', function () { alert('helo'); })
This works only If I manually type something in the textbox, but in my case where an external javascript is setting the textbox value, not working.
I created a little jsfiddle to show this:
https://jsfiddle.net/6vnuqxa0/
To try out:
Click on Choose pickup point
Select something from list and click on "Choose this pick up point".
Any ideas how to resolve this issue?
The selected answer to jQuery watch for domElement changes? suggests binding to the DOMSubtreeModified event. I have tried iin your fiddle and it works! The answer does mention that this event may be deprecated, but it is worth looking into.
In your case, add an id to your div so that you have:
<div id="packeta-selector-branch-id" class="packeta-selector-branch-id"></div>
Then the following code will trigger the alert when the contents of that div change.
$('#packeta-selector-branch-id').bind('DOMSubtreeModified', function(e) {
if (e.target.innerHTML.length > 0) {
alert('helo');
}
});
Otherwise, I would look at the widget itself and try and determine if it fires any events on select. If so, you could attach some behaviour to that event.
trigger('change') when click button. but a ID or name on your input would be better
$(document).off('click', '.button select-branch').on('click', '.button select-branch', function(){
$('.packeta-selector-branch-id').trigger('change');
})

How to determine if an Element was created dynamically

I have an existing system built using jQuery, Backbone.js and a REST-ish back-end written in C#. The application is an SPA with forms to fill and navigation. My job is to build a "Navigation Interceptor" to connect on the application so the system detects whether a field was modified in the current view so that when the user navigates, he will be warned that fields were modified and be requested to save or cancel the changes.
The way I designed it is using jQuery. To make it short, I use a selector on input, select, etc.. and bind a change event to it. Then I use a selector on links and buttons, unbind all click events, bind my "interceptor" (if a field has changed, ask before navigating) and then rebind all click events after my interceptor. I use stopImmediatePropagation() to cancel the regular navigation events, resulting in a kind of wrapper around the events.
By doing so, I have 2 problems:
Calling .val() on a field does not trigger the change event which is fine since I populate the fields dynamically. The problem is that the bootstrap date pickers does not seem to be setting the value using .val() resulting in all date fields having the "changed" state when initialized.
Elements dynamically created (e.g.: field in accordion panel created after the page has loaded) don't accept the events resulting in forms not firing the change event of my navigation interceptor.
My question is regarding the 2 above elements:
Is there a way to determine if a specific field is a date picker and bind the change event on that field so that when I populate it, the change event does not fire, but when the users do, it does (I tried binding on the changeDate event but the setDate method seems to be firing the changeDate event also)?
Is there a way to determine if the element was dynamically created (e.g.: $(''))? The problem is that I do not have a specific selector for a single field, so I think I cannot use delegation ($(document).on('change', 'someFieldSelectorICannotKnow', function () {});). All I have is a handle on the jQuery element ($(this) in a .each(fn) iteration).
#2 Solved using event delegation on all fields and skipping the handler if the field is not a form field
Solution of #2:
NavigationInterceptor.prototype.bindChangeEventOnAllEditableFields = function () {
var self = this;
var fieldsSelector = $(this.configuration.selectors.formFields.join(', '));
$(fieldsSelector).each(function () {
var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, $(this));
if (isFormField && self.configuration.debug.highlight.fields.unchanged && $(this).attr('type') === 'radio') {
$(this).parent().css('background-color', self.configuration.debug.highlight.fields.unchanged);
} else if (isFormField && self.configuration.debug.highlight.fields.unchanged) {
$(this).css('background-color', self.configuration.debug.highlight.fields.unchanged);
}
});
$(document).on('change', fieldsSelector, function (event) {
var field = $(event.target);
var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, field);
if (isFormField) {
self.hasFieldChanged = true;
if (self.configuration.debug.highlight.fields.changed) {
if (field.attr('type') === 'radio') {
field.parent().css('background-color', self.configuration.debug.highlight.fields.changed);
} else {
field.css('background-color', self.configuration.debug.highlight.fields.changed);
}
}
}
});
return this;
}
var unchangeable_classes = ['decorative', 'constant'];
$(document).on('change', 'input,select,textarea', function () {
var $this=$(this);
for(var i =0;i<unchangeable_classes.length;++i){
if($this.hasClass(unchangeable_classes[i]))
return;
}
global_changed = true;
});
Why doesn't this work, it should? (Edited in response to comment.)
My thoughts>>
1)A way to stop calling changeDate() after calling setDate(), you could just call event.stopPropogation(), it will prevent the event from bubbling up
2)while creating a dynamic element, you could add any property of your wish. For eg
var iDiv = document.createElement('div');
iDiv.isDynamic = true;
then while iterating through the element, check for isDynamic property
Why not add a benign class tag to the element
$('#foo').addClass('bar');
then you can check for the class to see if it was created
if ($('#foo').hasClass('bar'))
alert('was created');
Note that when you add elements you have to re-attach the events. So if you have a global document event and then add an element, that element won't be included unless you explicitly attach the new element.
I'm posting the answer for my question #1.
What I did is modify bootstrap's source. When calling setDate like so:
$('#myDateInput').datepicker('setDate', new Date());
The code goes through the function setDates which calls update and setValue, the first one resulting in the date being set in the datepicker itself, the second one setting only the value in the input text field. What I did is remove the call to 'change' which triggers the change event on the field and left the custom event 'dateChange'. This results in my code not firing the change event when I call setDate, but calls it when the user sets a date using the picker itself.

Override parrents onClick event with checkbox onClick?

First, sorry for my bad English.
I'm making a Coupons site and have trouble with selecting and deselecting the coupons. Each coupon is in a DIV 'box' in which there is a checkbox.
I made a onClick function on the DIV box (so the user can select the coupon by clicking on anything inside the DIV box. What I need now is, when the user want to deselect the coupon (by clicking on the checkbox inside the DIV box), I need to 'override' the DIV's onClick function (execute the checkbox onClick event, not the DIV's onClick event).
I know that everyone prefers some code as an example, but the question/problem is simple and I don't think you need all of my un'useless code inside the events/functions :)
Thanks :)
It seems like you want stopPropagation if the checkbox is being unchecked: http://jsfiddle.net/8Dcq8/.
$("div").click(function() {
alert("add"); // clicking anywhere in div to add coupon
});
$(":checkbox").click(function(e) {
if(!this.checked) { // if unchecking, remove coupon
alert("remove");
e.stopPropagation(); // don't run parent onclick
}
});
If the <div> click handler looks something like this:
var $boxes = $('div.box');
$boxes.on('click', function ()
{
// do whatever to select the coupon
});
Then the checkbox handler should look something like this:
$boxes.find('input[type="checkbox"]').on('click', function (event)
{
event.stopPropagation();
// do whatever to deselect the coupon
});
See event.stopPropagation().
You have to cancel bubbling. See here for an explanation.
You can use the jQuery Alternative, or create sub-elements with onClicks that don't target your checkbox. you might be able to use something like this also.
document.getElementById('element').checked.onreadystatechange=function(){
//code
}
good luck

Jquery : how to trigger an event when the user clear a textbox

i have a function that currently working on .keypress event when the user right something in the textbox it do some code, but i want the same event to be triggered also when the user clear the textbox .change doesn't help since it fires after the user change the focus to something else
Thanks
The keyup event will detect if the user has cleared the box as well (i.e. backspace raises the event but backspace does not raise the keypress event in IE)
$("#inputname").keyup(function() {
if (!this.value) {
alert('The box is empty');
}
});
jsFiddle
As Josh says, this gets fired for every character code that is pressed in the input. This is mostly just showing that you need to use the keyup event to trigger backspace, rather than the keypress event you are currently using.
The solution by Jonathon Bolster does not cover all cases. I adapted it to also cover modifications by cutting and pasting:
$("#inputname").on('change keyup copy paste cut', function() {
//!this.value ...
});
see http://jsfiddle.net/gonfidentschal/XxLq2/
Unfortunately it's not possible to catch the cases where the field's value is set using javascript. If you set the value yourself it's not an issue because you know when you do it... but when you're using a library such as AngularJS that updates the view when the state changes then it can be a bit more work. Or you have to use a timer to check the value.
Also see the answer for Detecting input change in jQuery? which suggests the 'input' event understood by modern browsers. So just:
$("#inputname").on('input', function() {
//!this.value ...
});
Another way that does this in a concise manner is listening for "input" event on textarea/input-type:text fields
/**
* Listens on textarea input.
* Considers: undo, cut, paste, backspc, keyboard input, etc
*/
$("#myContainer").on("input", "textarea", function() {
if (!this.value) {
}
});
You can check the value of the input field inside the on input' function() and combine it with an if/else statement and it will work very well as in the code below :
$( "#myinputid" ).on('input', function() {
if($(this).val() != "") {
//Do action here like in this example am hiding the previous table row
$(this).closest("tr").prev("tr").hide(); //hides previous row
}else{
$(this).closest("tr").prev("tr").show(); //shows previous row
}
});
Inside your .keypress or .keyup function, check to see if the value of the input is empty. For example:
$("#some-input").keyup(function(){
if($(this).val() == "") {
// input is cleared
}
});
<input type="text" id="some-input" />

Categories

Resources