Rebind a JQuery function to an input field after innerHTML command - javascript

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()

Related

Calling a function , when element is Live

How can i call a function when element is live, i think we just raise a function by raising an event by live..
$('#a').live('click',function(){
//some code
});
but i need a function to be called when element is lived,Any Idea.
The context is
initially i dont have a select box , if i got a particular select box
then i want call a function that pushes result into it..
you can use on delegate event...
$(document).on("click",'#a',function(){
alert(clicked);
});
however,it is always recommended that you use the closest static elements that are in the HTML markup, then $(document) for better performance.. you can read more about on delegate event here..
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page
Live is deprecated and removed on jQuery 1.9. Use .on()
This enable click on any element with id #a added after page is loaded
$(document).on('click','#a',function(){
//Code here
});

jquery issue with on and live

I have the following code:
var $reviewButton = $('span.review_button');
$reviewButton
.live('click',
function(){
$('#add_reviews').show();
}
)
Later in the script, I use an AJAX call to load some content and another instance of $('span.review_button') enters the picture. I updated my code above to use '.live' because the click event was not working with the AJAX generated review button.
This code works, as the .live(click //) event works on both the static 'span.review_button' and the AJAX generated 'span.review_button'
I see however that .live is depracated so I have tried to follow the jquery documentations instructions by switching to '.on' but when I switch to the code below, I have the same problem I had before switching to '.live' in which the click function works with the original instance of 'span.review_button' but not on the AJAX generated instance:
var $reviewButton = $('span.review_button');
$reviewButton
.on('click',
function(){
$('#add_reviews').show();
}
)
Suggestions?
The correct syntax for event delegation is:
$("body").on("click", "span.review_button", function() {
$("#add_reviews").show();
});
Here instead of body you may use any static parent element of "span.review_button".
Attention! As discussed in the comments, you should use string value as a second argument of on() method in delegated events approach, but not a jQuery object.
This is because you need to use the delegation version of on().
$("#parentElement").on('click', '.child', function(){});
#parentElement must exist in the DOM at the time you bind the event.
The event will bubble up the DOM tree, and once it reaches #parentElement, it is checked for it's origin, and if it matches .child, executes the function.
So, with this in mind, it's best to bind the event to the closest parent element existing in the DOM at time of binding - for best performance.
Set your first selector (in this case, div.content) as the parent container that contains the clicked buttons as well as any DOM that will come in using AJAX. If you have to change the entire page for some reason, it can even be change to "body", but you want to try and make the selector as efficient as possible, so narrow it down to the closest parent DOM element that won't change.
Secondly, you want to apply the click action to span.review_button, so that is reflected in the code below.
// $('div.content') is the content area to watch for changes
// 'click' is the action applied to any found elements
// 'span.review_button' the element to apply the selected action 'click' to. jQuery is expecting this to be a string.
$('div.content').on('click', 'span.review_button', function(){
$('#add_reviews').show();
});

Javascript AddEventListener issue

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.

how to send invoked event to JS function from hyperlink

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.

jQuery .live() vs .on() method for adding a click event after loading dynamic html

I am using jQuery v.1.7.1 where the .live() method is apparently deprecated.
The problem I am having is that when dynamically loading html into an element using:
$('#parent').load("http://...");
If I try and add a click event afterwards it does not register the event using either of these methods:
$('#parent').click(function() ...);
or
// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...);
What is the correct way to achieve this functionality? It only seems to work with .live() for me, but I shouldn't be using that method. Note that #child is a dynamically loaded element.
Thanks.
If you want the click handler to work for an element that gets loaded dynamically, then you set the event handler on a parent object (that does not get loaded dynamically) and give it a selector that matches your dynamic object like this:
$('#parent').on("click", "#child", function() {});
The event handler will be attached to the #parent object and anytime a click event bubbles up to it that originated on #child, it will fire your click handler. This is called delegated event handling (the event handling is delegated to a parent object).
It's done this way because you can attach the event to the #parent object even when the #child object does not exist yet, but when it later exists and gets clicked on, the click event will bubble up to the #parent object, it will see that it originated on #child and there is an event handler for a click on #child and fire your event.
Try this:
$('#parent').on('click', '#child', function() {
// Code
});
From the $.on() documentation:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
Your #child element doesn't exist when you call $.on() on it, so the event isn't bound (unlike $.live()). #parent, however, does exist, so binding the event to that is fine.
The second argument in my code above acts as a 'filter' to only trigger if the event bubbled up to #parent from #child.
$(document).on('click', '.selector', function() { /* do stuff */ });
EDIT: I'm providing a bit more information on how this works, because... words.
With this example, you are placing a listener on the entire document.
When you click on any element(s) matching .selector, the event bubbles up to the main document -- so long as there's no other listeners that call event.stopPropagation() method -- which would top the bubbling of an event to parent elements.
Instead of binding to a specific element or set of elements, you are listening for any events coming from elements that match the specified selector. This means you can create one listener, one time, that will automatically match currently existing elements as well as any dynamically added elements.
This is smart for a few reasons, including performance and memory utilization (in large scale applications)
EDIT:
Obviously, the closest parent element you can listen on is better, and you can use any element in place of document as long as the children you want to monitor events for are within that parent element... but that really does not have anything to do with the question.
The equivalent of .live() in 1.7 looks like this:
$(document).on('click', '#child', function() ...);
Basically, watch the document for click events and filter them for #child.
I know it's a little late for an answer, but I've created a polyfill for the .live() method. I've tested it in jQuery 1.11, and it seems to work pretty well. I know that we're supposed to implement the .on() method wherever possible, but in big projects, where it's not possible to convert all .live() calls to the equivalent .on() calls for whatever reason, the following might work:
if(jQuery && !jQuery.fn.live) {
jQuery.fn.live = function(evt, func) {
$('body').on(evt, this.selector, func);
}
}
Just include it after you load jQuery and before you call live().
.on() is for jQuery version 1.7 and above. If you have an older version, use this:
$("#SomeId").live("click",function(){
//do stuff;
});
I used 'live' in my project but one of my friend suggested that i should use 'on' instead of live.
And when i tried to use that i experienced a problem like you had.
On my pages i create buttons table rows and many dom stuff dynamically. but when i use on the magic disappeared.
The other solutions like use it like a child just calls your functions every time on every click.
But i find a way to make it happen again and here is the solution.
Write your code as:
function caller(){
$('.ObjectYouWntToCall').on("click", function() {...magic...});
}
Call caller(); after you create your object in the page like this.
$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();
By this way your function is called when it is supposed to not every click on the page.

Categories