I am trying to write code that will add another row to a form automatically. It should only do this once for each form input with the class lastName.
The below code works. But it executes more than once. I want the code to only execute once for each form input with the class lastName. I am inexperienced with jquery and javascript, so I am unsure of how to approach this problem.
function AutoAdd() {
$('.lastName').focus(function(e){
$('#add_new',pupils_form).parent().before(pupils_row);
AutoAdd();
});
};
AutoAdd();
You can use the one method:
Attach a handler to an event for the elements. The handler is executed at most once per element.
$('.lastName').one('click', function(e){
$('#add_new',pupils_form).parent().before(pupils_row);
});
Also as you are binding a handler for the inputs you can put the handler outside of the function, note that your function calls itself and runs continuously. If you want to execute the handler on page load you can trigger the event:
$('.lastName').focus(function(e){
$('#add_new',pupils_form).parent().before(pupils_row);
}).focus()
For dynamically generated elements, you should delegate the event, try the following:
$(document).on('focus', '.lastName', function(){
$('#add_new',pupils_form).parent().before(pupils_row);
})
You can use data-* attributes, try the following:
<input type='text' class='lastName' data-run='go'/>
$(document).on('focus', '.lastName', function(){
if ( $(this).data('run') == 'go') {
$('#add_new',pupils_form).parent().before(pupils_row);
$(this).data('run', 'stop')
}
})
you are having an infinite call stack here. your AutoAdd will call itself again and again and ...
To avoid having to run your AutoAdd function on newly created rows, you can use jQuery's on()-function instead of focus():
$('#the-form').on('focus', '.lastName', function () {
$('#add_new',pupils_form).parent().before(pupils_row);
});
on() actually attaches to the form (you'll wanna change the selector #the-form) and listens to events that bubble up from children of said form.
Related
Explaining by example:
$(".myCheckboxes").click(function () {
...
});
Inside the click event function I have code that does various things depending on what checkboxes are checked.
I however need to run this code to initialize it first, kindof like this:
$(".myCheckboxes").click(function () {
...
}).click();
It runs the code and it gets initialized, but it also clicks on all my checkboxes making them all invert their value.
Is it possible to execute the inline click event function wihtout executing a click event?
I would very much like to keep the function inline to keep the flow of the code. Also, it's not big enough to have the function outside of the event, but it's not so small as I would like to write the code twice.
triggerHandler triggers only the handler:
$(".myCheckboxes").click(function () {
...
}).each(function(i, checkbox) {
$(checkbox).triggerHandler('click');
}
Note that you need to iterate the checkboxes if you wish to trigger the handler for all of them instead of just the first one:
while .trigger() will operate on all elements matched by the jQuery
object, .triggerHandler() only affects the first matched element.
Use a named function as the handler, bind it and execute it:
$(".myCheckboxes").click(clickHandler);
clickHandler();
You may consider to call the function triggerHandler who seems to do what you need.
$(".myCheckboxes").click(function () {
...
}).triggerHandler('click');
NB: I haven't tested this solution.
I have a situation where I am using the data attribute named data-command in many instances throughout a specific section of a site and instead of binding tons of separate click events I decided to just use the one and use a switch such as:
$('[data-command]').on('click', function(event) {
// Prevent default click action
event.preventDefault();
// Get command
var command = $(event.target).data('command');
switch (command) {
// Do stuff...
}
// Prevent default click action (IE 8)
return false;
});
However it has just become an issue when trying to get it to work on data loaded via AJAX.
This obviously works..
$('#existing_element').on('click', '[data-command]', function(event) {
...but since it is supposed to work on many different pages in that section of the site the above wouldn't work on all pages.
I could just make sure to give a specific id to the parent wrapper where I load all my ajax data, but that would mean making two separate binding events with a bunch of the same code.
I also could do this to cover all bases..
$(document).on('click', '[data-command]', function(event) {
...but that's probably not such a wise idea binding an element to the document.
Edit: Html data is being loaded into the DOM via jQuery's html method.
Any clean way I can handle this or should I just create two different binding events to handle each situation?
Event delegation is the best approach to bind events on dynamically created elements. Since you don't want to use event delegation, use following approach to bind events.
$('[data-command]').off('click').on('click', clickHandler);
// Somewhere in the same scope
function clickHandler(e) {
// Handle click event here
}
Add this after the dynamically created elements are added using html().
off('click') will first unbind the click event handlers that are applied previously and then on('click', will bind the click handler on all the elements matching selector.
Edit
This seems to be repeating the same code again and again. Can't I keep it DRY?
Yes, you can keep the code DRY and clean by creating a function to bind events and call the same function when you want to bind event.
function clickHandler(e) {
// Handle click event here
}
function bindEvent() {
$('[data-command]').off('click').on('click', clickHandler);
}
$(document).ready(bindEvent);
...
$.ajax({
...
success: bindEvent
....
I have some JavaScript code that binds a click event to certain elements click events as seen below.
$(".alert-message .close").click(function(e) {
$(this).parent().fadeTo(200, 0, function() {
$(this).slideUp(300);
});
e.preventDefault();
});
This is called in the document ready event so normally it works fine until i fire an ajax request that updates parts of the page. This newly created part doesn't have the click event added and i end up having to recall this code for every ajax request, resulting in a lot of duplication.
I am looking for a way to write this JavaScript code once and it to be called in any scenario. Is there some event handler that will be called after any ajax or normal request?
Bootstrap dismissable alert message work after any ajax request so there must be a way.
Depending on which version of jQuery you're using you should use either delegate or on instead of directly binding click. Try something like
$(document).on('click', '.alert-message .close', function(e) {
$(this).parent().fadeTo(200, 0, function() {
$(this).slideUp(300);
});
e.preventDefault();
});
http://api.jquery.com/on/
Use event delegation and bind the event to a parent of .alert-message .close that doesn't get recreated:
$(document).on('click', ".alert-message .close", function(e) {
Instead of that, you can use on:
$(parentDivOrContainer).on('click', ".alert-message .close", function(){...});
parentDivOrContainer can be any container element that is not affected by ajax call.
I have an element #div_1 which has inside the same document (not extern file) a plain JS function:
var trigger = false;
var div_1 = document.getElementById('div_1')
div_1.onclick = function() { trigger = true; };
and in an extern JS file I have a jQuery button click on the same element:
$(document).ready(function() {
$('#div_1').click(function() {
// some actions here
});
});
The problem is that it does ignore the jQuery clickhandler completely. Is there no way to have two seperate click handler which work both?
There must be something else going on in your code because you can certainly have multiple event handlers on an object.
You can only have one handler assigned via onclick, but that should, in no way, interfere with the jQuery event handler. Please show us a reproducible demo in a jsFiddle because there is likely some other problem with your code causing this.
FYI, I'd strong suggest you not use the onclick attribute for event handlers because there is danger of one event handler overwriting another, something that does not happen when using .addEventListener() or jQuery's .click(). But, neither .addEventListener() or jQuery's .click() will overwrite the onlick.
Here's a working demo that shows both event handlers working just fine: http://jsfiddle.net/jfriend00/4Ge52/
I hope I'm making the question clear.
Say you have some check-boxes (or any other type of element for that matter) for which you register events handler when the page loads. Then you add some more check-boxes using AJAX (so no page reload). But you also want these newly added check-boxes (after the page was loaded) to have the same registered events handlers?
What I tried was this but I feel there has to be a better approach:
$(document).ready(function () {
// Register custom envets handler
registerCustomEventHandlers();
$('a').on('click', addExtraFields);
});
function registerCustomEventHandlers() {
$('input.class_name').on("change", sayHelloWorld);
}
function sayHelloWorld() {
alert('Hello world');
}
function addExtraFields() {
// insert some checkboxes...
// register the events handler again for the newly added fields
registerCustomEventHandlers();
}
So basically inside the function that adds the check-boxes I register again all the events handlers. I was looking at something like this $(document).change(function() {}); but apperently it is not supported by all browsers...
Any suggestions?
You can delegate the event to the document instead so that they will be applied to all future inputs as well. You don’t even need to put it in a domReady event, since the document is always available:
$(document).on("change", "input.class_name", sayHelloWorld);
function sayHelloWorld() {
alert('Hello world');
}
function addExtraFields() {
// insert some checkboxes, they will have the same handler attached when inserted
}
Demo: http://jsfiddle.net/gdX3R/1/
I would recommend against using live selectors because of these reasons
Shortly summed up, it's a performance issue because it messes with every click event.
Instead, just use delegate like described in the post on lowest common parent element of the inputs (most likely a form):
$('#yourFormId').delegate('.class_name', 'click', function() {
// what you want to do
});
You can find a jsfiddle here
And don't use selectors like input.class_name (unless there elements other than input with that class name). They're slower than .class_name because they're looping through all the inputs in the form searching for elements with that class rather than just selecting by class.
As of jquery 1.4 you can always use live() too http://api.jquery.com/live/ which allows you to attach handlers now and in the future to any matching elements.
the way this is done in Jquery is such that you don't need the object to be present when creating the handler.
You could use:
$(document.body).on("click", "input[type='checkbox']",
function(){alert($(this))}
);
This will be applied to any new check-box added to the page, no matter timing.