I have a message box. When I click on submit it only works for the first time. Are the onclick events removed?
The code is like this :-
$("#message-box #send-message-btn").click(function(){
var messageText=$("#message-box #textarea").val();
$.get("getUserName",function(username,status){
$.get("getUserByUserName?username="+username,function(user,status){
var sentFrom=user.userId;
var today=new Date();
var today=getDateInFormat(today);
today=today+"Z";
var time=today;
var ajaxData= {
messageTypeId,
messageText,
messageReference : referenceId,
context,
sentFrom,
time
}
$.ajax({
url:"/addMessages",
data: JSON.stringify(ajaxData),
type: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
success : function(data) {
console.log("inside sucess of add messages");
$.get("/getMessagesByTypeContextReference?referenceId="+referenceId+"&&context="+context+"&&messageTypeId="+messageTypeId,function(messages,status){
var gets=[];
$.each(messages,function(i,message){
message.timestamp=getDateInFormat(new Date(message.time).addHours(-8));
gets.push($.get("getUserByUserId?userId="+message.sentFrom,function(user,status){
message.sentFromName=user.firstName+' '+user.lastName;
}));
})
$.when.apply($,gets).then(function(){
rowData.messages=messages;
$("#message-box").html('');
callHandlebars("#message-box","message-form-template",[],rowData);
})
})
},
error : function (exception) {
console.log("exception :"+exception);
}
});
})
})
})
After submitting the message in my database I am reloading the message box html. Is that removing the event handler? What is the solution?
You attach the click with this selector $("#message-box #send-message-btn") but in your success callback it looks like you reload everything in message-box so the button send-message-btn would be replaced and any attached events lost. You can use event delegation to keep those events attached or simply reattach them after replacing the HTML of message-box.
To leave them attached with delegation try replacing:
$("#message-box #send-message-btn").click(function(){
with:
$("#message-box").on('click', '#send-message-btn', function () {
This attaches the event to message-box and because of event bubbling allows message-box to pass the event back to send-message-btn even after he has been replaced in the DOM.
You are reloading the whole div on success. This makes you lose the click event, so it will not trigger again.
You can fix it by:
Re-adding the event after the div is reloaded (tested, but not really beautiful code)
Use on http://api.jquery.com/on/ instead of click (not tested, last time I used something like this was called "live", but it seems now is deprecated)
Related
I have a page where I return users posts, these posts can be commented on the fly using some jquery code, after a new comment is posted I insert the new comment under the post along with a Delete button. The problem is the Delete button doesn't work on the newly inserted element unless I reload the page. I read that the solution is using the .on() method however I am a little confused re how to implement this.
I have one function that updates the post part with the newly inserted comment and this is the function that deletes the comment:
$(document).ready(function () {
$("button[id*='deletecmnt_']").click(function () {
var id = this.id.replace('deletecmnt_', '');
var comment_card_id = ('#comment_' + id);
var token = $(this).data('token');
$.ajax({
url: '../comment/' + id,
type: 'post',
data: {_method: 'delete', _token: token},
success: function () {
// Checks for display of comment card and removes it
if ($(comment_card_id).is(":visible")) {
$(comment_card_id).fadeOut("fast");
}
}
})
})
});
I don't understand what needs to be changed here and how.
You need to use event delegation for elements added dynamically. In your .on() method, you need to add the selector that you want the handler attached to after it's created.
$(document).ready(function(){
$("body").on("click", "button[id*='deletecmnt_']", function () {
// codes
}
});
This will listen for clicks on elements not yet created that match your selector. Here's the JQuery API doc page for more info: http://api.jquery.com/on/
I'm working on a script to check if a file exists every 5s on onclick event. When it exists, I notify the client and reset the counter. First file check everything works fine, but when I check another file (click on another link with other data-file), it checks again both files and first file check is looping forever until I refresh the page. I tried everything I could think of, nothing worked. Please help!
var intervalCheck;
function isFileExists(file) {
$.ajax({
type: 'HEAD',
url: '/apps/'+file,
success: function() {
alert('found '+file);
clearInterval(intervalCheck);
},
error: function() {
}
});
}
$('#dialog').on('show.bs.modal', function(e) {
var file = $(e.relatedTarget).data('file');
$("a#checkfile").click(function() { intervalCheck = setInterval(function() { isFileExists(file); },5000); });
});
You must bind click event to only a#checkfile in clicked #dialog. Otherwise it will bind event to all a#checkfile elements. So when you open dialog for second time there will be 2 events on the a#checkfile link.
$(this).find('a#checkfile')
UPDATE
If there is one dialog contains multiple links, you can use jquery's one function for one-time events.
$('a#checkfile').one('click', function(){});
I am wondering if there is a way to get element id without clicking. I have data inside the divs that needs updating and printing. I can do exactly what I want by clicking the div. The data gets updated, printed, and disappears until the next div shows up. This is jQuery I am using.
$(document).ready(function(){
$('.store').click(function(){
the_id =$(this).attr('id');
$(this).fadeOut('slow');
$.ajax({
type: 'POST',
url: "update.php",
data:{id:the_id},
success:function(){
print_div();
}
});
});
});
So is there a way to tweak that .click function so that the data automatically gets updated, printed, and disappear without the actual clicking?
You can loop through the divs on document ready. I don't know if this is exactly what you are asking, but this way, you will know the ID of the elements without user interaction.
$(document).ready(function() {
$('.store').each(function() {
var the_id = $(this).attr('id');
$(this).fadeOut('slow');
$.ajax({
type: 'POST',
url: "update.php",
data: {
id: the_id
},
success: function() {
print_div();
}
});
});
});
In short, no.
JavaScript relies on events - whether timed or created by an interaction (forced or organic) to add methods to the call stack. If you'd like, you can trigger an event (a forced event) using jQuery's trigger method on an event. On the other hand, you can set up a timer using setInterval (a regular action) or setTimeout (a delayed action) to trigger the event. Other than that, you have to rely on the user interaction to trigger events.
You could get clever on what triggers the callback function to the click method - you can look at the user's mouse or scrolling behavior and reload the element or even on some sort of keyboard event. It's really a matter of what will provide the best user experience in your context.
Here is some boilerplate to help:
$(document).ready(function(){
$('.store').click(storeHandler);
$('#someOtherElement').on('event', storeHandler);
setTimeout(storeHandler, 1000);
});
function storeHandler(event) {
var theElement = $(event.target); // the event object is very useful
var theId = theElement.attr('id');
theElement.fadeOut('slow');
$.ajax({
type: 'POST',
url: "update.php",
data:{id:the_id},
success:function(){
print_div();
}
});
}
The goal is to let you replicate the behavior given some event.
I have a simple textarea where users can input text which is then passed through via AJAX to a URL once they hit the return key. My issue is that on the first press of the return key the text data is sent once, on the second it's sent twice, and so on incrementing my one each time.
After some reading up I realise that if I was using a form submit I'd have to unbind it to prevent this happening. I've tried adding a value flag to prevent the multiple events, but have only got so far as to get it to trigger once only.
My code is as follows. Any guidance on how to prevent the incrementing events would be appreciated - as you can probably tell my confidence/knowledge in Javascript isn't the best. Thank you!
$(function() {
$("#myTextarea").keypress(function(e) {
// If the user hits the return key
if(e.which == 13) {
e.preventDefault();
$.ajax({
success: function(){
var modal = $('#myModal'), modalBody = $('#myModal .modal-body');
modal
// Load the webpage result within the modal Body
.on('show.bs.modal', function () {
modalBody.load('http://www.things.co.uk/things' + document.getElementById('myTextArea').value)
})
.modal();
// Hide the modal after five seconds
myModalTimeout = setTimeout(function() {
$('#myModal').modal('hide');
}, 5000);
}
});
}
});
});
Edit: I solved this by using one() for my modal event via http://www.andismith.com/blog/2011/11/on-and-off/. Thank you everyone.
You must attach the event handler only once. I suppose you're getting the JS in your AJAX response, and executing it again and again on each AJAX load. Removing and re-attaching the handlers is a hacky solution.
To avoid to attach the event handlers more than once, simply put your script in a part of the page which is not reloaded by AJAX, so the event is attached only once.
You can even attach an event handler to an element that is reloaded by ajax using delegated events: Understanding Event Delegation
With this technique, you attach the event handler to a container parent element which is not reloaded by ajax, and handle the events of the reloaded children specified by a filter.
$( "#container" ).on("<event>", "<children filter>", function( event ) {
// code to handle the event
});
Note that in this sample #container is the element which isn't reloaded by ajax. And <children filter> is a jquery selector that chooses the children whose event mus be handled. (<event> is obviously the event name, like click or keyPress).
Explanation: when the event is trigger in the child element, it pops up to the container. The container catches it, and checks that the children passes the filter. If so, the vent is handled.
If there are no more event handlers on myTextarea div code below should suffice.
If there are multiple event handlers attached to keypress event you will have to use named function and remove it using $.unbind() more on how to do this.
$(function() {
$("#myTextarea").off();
$("#myTextarea").keypress(function(e) {
// If the user hits the return key
if(e.which == 13) {
e.preventDefault();
$.ajax({
success: function(){
var modal = $('#myModal'), modalBody = $('#myModal .modal-body');
modal
// Load the webpage result within the modal Body
.on('show.bs.modal', function () {
modalBody.load('http://www.things.co.uk/things' + document.getElementById('myTextArea').value)
})
.modal();
// Hide the modal after five seconds
myModalTimeout = setTimeout(function() {
$('#myModal').modal('hide');
}, 5000);
}
});
}
});
});
So I have a page that loads the data into the page through the following ajax function.
$(document).ready(function(){
function loadData(page){
$.ajax
({
type: "POST",
url: "inc/load_data.php",
data: "p="+page+"XXXXXXXXXXX",
success: function(msg)
{
//alert(msg);
$("#container").ajaxComplete(function(event, request, settings)
{
$("#container").html(msg);
//**MODIFIED CODE
$(document).delegate('a.vote_up','click', f_vote_up);
});
}
});
}
});
//Loaded Message
$msg.='<span class="vote_buttons" id="vote_buttons'.$row['id'].'">
</span>';
The message that is loaded has some links that need to work with a another Ajax function(given below), which is apparently not working. The second function(below) is loaded before the data is loaded into the page. I suspect, may be since this function is loaded way before the data is loaded, the second function is not recognizing the click on vote_up. Is there any way to fix it??? I'm not too familiar with AJAX, I would really appreciate some help.. Thank you
$(function(){
$("a.vote_up").click(function(){
//get the id
alert("Hi");
//REST OF THE CODE
}
//***NEW FUNCTION
function f_vote_up(){
//get the id
the_id = $(this).attr('id');
//REST OF THE CODE
$("span#vote_buttons"+the_id).html("Hello, Testing Response!");
alert("End of Func!"); // <
}
When you call that second function, it's only grabbing all the a.vote_up elements that currently exist on the page. When you add more links to the page later on, they don't know to listen for the click.
You can do one of two things to fix this:
Add the click listener to each new link when you add it to the DOM. But this is a bit of work, because you'd have to change how your AJAX function builds the links, and you'd have to turn that click-listener-assigning function into something standalone that you could use at any time.
Instead of doing using the click method, use the delegate method instead:
$(document).delegate('a.vote_up', 'click', function () { ... });
More info on event delegation with jQuery.
you should bind your click event after you load the html
$.ajax
({
type: "POST",
url: "inc/load_data.php",
data: "p="+page+"XXXXXXXXXXX",
success: function(msg)
{
//alert(msg);
$("#container").ajaxComplete(function(event, request, settings)
{
$("#container").html(msg);
$("a.vote_up").click(function(){
//get the id
alert("Hi");
//REST OF THE CODE
});
});
}
});
You can use the live function to bind an event to dynamically created elements, i.e.:
$("a.vote_up").live('click', function(){
//get the id
alert("Hi");
});
http://api.jquery.com/live/
This will effectively bind this click event to all elements which match the a.vote_up selector, now and in the future.