I have two select-boxes, each of them is in span element with specific id. The first select-box is country, the other one is city list. When I select a country the innerHtml of city select-box container span is replaced by response of ajax function everything is good. But I want to fire a function by useing onchange attribute of selectbox if at the begining of page loading addeventListener function works fine but affter replacement of innerHtml of span it does not work and after replacement the id of city selecbox is same es before replacement. I am just using.
document.getElementById('to_city').addEventListener('change',doSomething,false);
this code is initialized by onload of window element.
It works without ajax replacement but dont after.
When you replace contents with AJAX you need to bind event again. so its good idea to bind event again after replacing content.
There is a way to avoid it using event bubbling.
JQuery 1.4+ supports onchange event propagation so you can use jquery delegate function to achieve same. http://api.jquery.com/delegate/
with Jquery only one line do the work.
$("#container").delegate("#to_city", "change", doSomething); // Workd in all browsers
I ignored IE in below example as you are using addEventListener which is not supported by IE.
Without Jquery
Working example (Not working in IE) : http://codebins.com/bin/4ldqpb1/2
document.getElementById("container").addEventListener( 'change', function(e) {
var targ=e.target;
if (targ.id == "to_city") { //you just want to capture to_city event
//DO STUFF FOR SELECT
//DO STUFF
doSomething();
alert("id: " + targ.id + "\nvalue: " + targ.value);
}
}, false)
Explanation:
When you bind any events they are bound to that particular element not the selector or ID. so when you replace the content and new replace element with the new element with the same ID, new element doesnt have any event attached. so you need to attache event again. so if you attach event after AJAX content replace doSomething will work. but that is not a very good solution.
We are using event bubbling concepts. many events are bubbled to the top of the document. (IE doesn't bubble change event)
So we write handler on the container and listen for the event. each event has a target or srcElement which says which dom element firing this event. if the dom element is what we are looking for execute function. in this can we are looking for element with ID to_city that's why if condition.
Related
I use jQuery to add some HTML to the DOM. After the insertion I would like to create an eventhandler which is called on keyup and clicks on the link added to el. However, jQuery does not find the a element as it was added after loading the page.
var el = $("#name");
// add content to el
$(document).keyup(function(e) {
el.find('a').click();
});
How can I update the DOM in el? I know that there is on() (and its predecessors) in jQuery. However, they do not help me as the event is not registered on the added element itself, but on the document and another event just happens on the newly added element. Any ideas on how to solve this?
Thanks to the response of #Johan I was doing further debugging and found the solution:
el.find('a')[0].click();
So the real problem was not the changing DOM but the click() event that apparently can only be applied to a single element and not to a list of only one element.
Some further discussion about click() not firing can be found here: Can I call jquery click() to follow an <a> link if I haven't bound an event handler to it with bind or click already?
I have a target div el with some components displayed. These components have some events attached (on mouse over, on click). I don't control this code neither those events. They are just there. I'd like to render a widget inside this div. To do so I'm doing something like:
var save = el.innerHTML;
el.innerHTML = "my widget code";
When my widget finishes its process I want to get back to the original content so I do:
el.innerHTML = save;
The components previously saved are correctly replaced but the events attached to them don't work anymore.
I can't hide, show divs. I need to replace the innerHTML to have the exact style and positioning.
What would you do in my case?
I'm using jQuery if it helps.
Thanks.
When you serialize DOM elements back to HTML, all the event handlers and bound data are lost.
If you have DOM, work with it, not with HTML:
var save = $(el).children().detach();
$(el).html(widgetHTML);
// later
$(el).empty().append(save);
You might find .detach useful - http://api.jquery.com/detach/
It does the same as .remove but keeps all the associated jquery element data - which will include any event listeners added with jquery, though you will lose any 'regular dom events' attached.
you'd have to re-attach the element with jQuery too:
var stored = $(el).detach();
//… wait for something to finish, then reattach
stored.appendTo('#outer');
You can delegate the event to your el element since it doesn't seem to change - Those newly added elements did not exist at the time of binding
$(el).on('click','yourelementtoattachevent',function(){
// replace click with your event/events
// your code goes here
});
This is assuming you are using jQuery 1.7+, for others use
$(selector).live(); // jQuery 1.3+
$(document).delegate(selector, events, handler); // jQuery 1.4.3+
$(document).on(events, selector, handler); // jQuery 1.7+
Im using JQuery to check the file size and name from an html file input field. The input field is:
<div id="uploadFile_div">
<input name="source" id="imageFile" type="file" style ="border: 1px solid #576675;">
</div>
And the JQuery:
$(document).ready(function(){
$('#imageFile').bind('change', function() {
alert("Test");
//.... perform input checks...//
});
});
Now, I have a selection box, where the user choose between image file or video file, and based on it I send the file to different servers and also perform appropriate checks. In order to reset the input field (I do it when the user changes the selection box from Video to Image and vise versa) I use this JavaScript trick:
document.getElementById('uploadFile_div').innerHTML = document.getElementById('uploadFile_div').innerHTML;
But After 1 execution of this JavaScript, The JQuery isn't binded and I don't see the "Test" alert when I select files.
How can i rebind the JQuery ?
Thanks.
You could use a delegated event handler, binding the event to the parent div:
$('#uploadFile_div').on('change','#imageFile', function() {
// etc
Demo: http://jsfiddle.net/SfgpS/
(If you're using a version of jQuery older than 1.7 use .delegate() instead of .on(). If you're using a really old version of jQuery use .live().)
When you rewrite the .innerHTML of the container that effectively erases the old input element including event handlers that were bound to it, and then creates a new input. So you could re-run your original .bind() statement at that point to bind a handler to the new input.
With a delegated event handler as for that syntax of .on() you bind the handler to the container, i.e., to the div in this case. Events that happen to the container's child(ren) bubble up to the container (and then right on up to the document). So in this case when a change event reaches the div jQuery checks whether it originated with an element matching the selector from the second parameter of .on() and if so calls the your handler function. This lets you handle events on elements that don't exist at the time you create the handler. It doesn't matter if you remove and re-add the child elements because the handler was bound to the container.
(Note that if you leave out that second parameter to .on() it creates a non-delegated handler just the same as .bind().)
Why not just wrap the whole mess up in a function you can call both onReady and then whenever you want to reset the upload form?
var resetUpload = function() {
document.getElementById('uploadFile_div').innerHTML = document.getElementById('uploadFile_div').innerHTML;
$('#imageFile').bind('change', function() {
alert("Test");
//.... perform input checks...//
});
}
// run on ready
$(document).ready(function () {
resetUpload();
});
What version of jQuery are you using?
You could use .live() or .on() (jQuery >= 1.7) instead of .bind()
this pattern href="javascript:stop(this); pass the hyperlink object to stop function, but i also want to pass invoked event to that function. how can i do that? my records are getting load through ajax so cant attach .click(function(event){}) with it. and if i attach click on each AJAX call then web slows down on IE6.
please guide me
Thanks
You have jQuery so you can use delegates/live events instead of inline events or those nasty javascript: hrefs:
$('#parent').on('click', 'a', function(e) {
// you can use this and e (the event) here
});
#parent needs to be an element that already exists and will contain the newly added elements. a is the selector to match the elements inside #parent on which you want the click events to trigger. You may use $(document) instead of $('#parent') to resemble .live() from older jQuery versions, but using a parent element that is closer to the inner elements is better for performance reasons.
I am a bit confused, I have a bunch of elements that get added via jquery using a ajax call and I want to attach a click handler to them (there could be a lot).
But I have no idea how to even begin this, I looked at .on and it is really confusing. I want to attach a click event handler for a certain class so that when I click on it, I get the this.id and then do stuff with it.
What you're trying to do is called event delegation.
You want to set the event listener on a higher element in the DOM that'll never change, but only fire off the event handler if the child element that has been clicked matches a specific selector.
Here's how it's done with jQuery's .on():
$(document).on('click', '.your-selector', function(){
alert(this.id);
});
P.S. You could probably apply the event listener to an element lower down in the DOM tree...
This will get you the id of a clicked element with the class "test"...
$(".test").on("click", function() {
var id = $(this).attr("id")
});
You'll need to run that after the ajax call returns. It will only bind the click event to elements that exist when it runs, so it's no good at document.ready.