Ajax call works only first time - javascript

This is my code, to modify the content of a table cell, clicking a link "Open/Close" of the sibling cell.
The link works good the first time but on the second click, the execution start again from
$("a[href*='close']").click(function (event)
even if the new link contains "open" and not the word "close" anymore.
Why have I this behaviour?
Which is the problem? How can I solve it?
Thanks in advance!
$(document).ready(function()
{
$("a[href*='close']").click(function (event)
{
event.preventDefault();
var click = $(this);
console.log(click);
var url = click.attr("href");
console.log(url);
var nid = url.split("/")[1];
console.log(nid);
// var url = "close/" + nid;
// console.log(url);
$.get(url, function(data, status)
{
if (data.status == 1)
{
console.log(data.res);
click.text("Open");
var new_url = url.replace("close", "open");
console.log("New Url = " + new_url);
click.attr("href", new_url);
click.parent().prev().text(data.res);
}
else
{
console.log("Error");
}
});
}); // CHIUDE FUNZIONE
$("a[href*='open']").click(function (event)
{
event.preventDefault();
var click2 = $(this);
console.log(click2);
var url = click2.attr("href");
console.log(url);
var nid = url.split("/")[1];
console.log(nid);
// var url = "open/" + nid;
// console.log(url);
$.get(url, function(data, status)
{
if (data.status == 1)
{
console.log(data.res);
click2.text("Close");
var new_url = url.replace("open", "close");
console.log("New Url = " + new_url);
click2.attr("href", new_url);
click2.parent().prev().text(data.res);
}
else
{
console.log("Error");
}
});
}); // CHIUDE FUNZIONE

As I stated in my comment to the question, you can use a delegate event binding, rather than juggling event bindings, to allow events to only be processed by the logic that you want them to be processed by.
$(document).on('click', 'a[href*="close"]', function (event) {
event.preventDefault();
console.log('close');
event.target.href = '#open';
});
$(document).on('click', 'a[href*="open"]', function (event) {
event.preventDefault();
console.log('open');
event.target.href = '#close';
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Toggle

Related

Using javascript object to call function and virables

Am trying to advance my javascript code, by using it as an object so i can call it when needed but it doesn't work. Please can someone help me out i will appreciate it.
var AppObject = {
var targetElement = "#AjaxLoadBodyContentLoader";
init: function (hashUrl, defaultBack){
if(hashUrl != defaultBack && hashUrl != ""){
var LoadHashUrl = hashUrl+' #AjaxLoadBodyContentLoader';
$('#AjaxLoadBodyContentLoader').load(
LoadHashUrl,
{"async_content" : "true", "PrevLink" : defaultBack}
);
}
},
asyncShowContent: function(){
/*$.getScript("external.js");*/
$(this.targetElement).show('normal', this.asyncPregressBar);
},
asyncPregressBar: function(){
$('#preloader').fadeOut();
$('#status').fadeOut();
},
asyncLoader: function(){
$(this.targetElement).load(
this.linkPath,
{"async_content" : "true", "PrevLink" : this.PrevLink},
function(responseTxt, statusTxt, xhr){
this.asyncShowContent();
console.log("Status: " + xhr.status + " | Text: " + xhr.statusText);
}
);
},
asyncExtecute: function(e){
var targetUrl = e.target.href;
if(typeof targetUrl == 'undefined' || targetUrl == ""){
targetUrl = $(this).attr('href');
}
var linkPath = targetUrl + ' ' + this.targetElement;
var PrevLink = $(this).attr('data-page-link');
window.location.hash = targetUrl;
$('#preloader').fadeIn();
$('#status').fadeIn();
$(this.targetElement).hide('fast',this.asyncLoader);
}
}
Using the above code without adding it inside AppObject={}, work very fine, but i want to advance it and learn more how to use javascript object.
Usage
$(function(){
AppObject.init(
window.location.hash.substr(1),
location.href.replace(location.hash,"")
);
$(document).on('click', 'a.LoadPage', function(e){
AppObject.asyncExtecute(e);
});
});
As #musefan says in a comment, you have a syntax problem:
This is wrong:
var AppObject = {
var targetElement = "#AjaxLoadBodyContentLoader";
...
}
This is a variable declaration:
var targetElement = "#AjaxLoadBodyContentLoader";
Inside an object, you need to use key/value pairs:
var AppObject = {
targetElement : "#AjaxLoadBodyContentLoader",
...
}
EDIT: e is undefined
e should be your event, you need it in asyncExtecute,
var AppObject = {
asyncExtecute: function(e){
e.preventDefault(); // Add this line, to prevent the browser to immediately navigate to other window
var targetUrl = e.target.href;
...
}
}
$(function(){
...
$(document).on('click', 'a.LoadPage', function(e){
AppObject.asyncExtecute(e); // Here you are passing the event object to asyncExtecute
});
});
Problem is the way you are adding property to your object. Please add it as below:
var AppObject = {
targetElement: "#AjaxLoadBodyContentLoader",
//remaining code---
};

Odoo Javascript after reload a div onchange event is not triggered anymore

This is Odoo 10.0 FrontEnd.
In my "site" i load dynamically divs when the user select some fields and those divs contains checkbox and input box.
When the user change them i have some functions that write new value on DB.
I'm trying to reload only the div that contain all rows instead of all page, but with my code if i use
$('#container_lines').load(location.href + " #container_lines");
instead of
window.location.reload();
If i click again the checkbox the onchange event is not triggered!
Here is the Javascript
odoo.define('website_sale_order_checklist.checklist_line', function (require) {
'use strict';
var ajax = require('web.ajax');
var core = require('web.core');
var session = require('web.session');
var Model = require('web.Model');
var _t = core._t;
//var body = $("body");
//IF some ajax start the windows show a loading bar
$(document).on({
ajaxStart: function () {
$("body").addClass("loading");
},
ajaxStop: function () {
$("body").removeClass("loading");
}
});
console.debug('website_sale_order_checklist');
$(document).ready(function () {
//If user select another stage save it
function update_line_value(checklist_line_id, checklist_line_view_id, checklist_line_view_type) {
//Take the id of the checklist line int
var checklist_line_id_int = Number(checklist_line_id);
//Take the value of the input tag for text and value
//take the model
var Checklists = new Model('sale.order.checklist.line');
//if the selected view is a checklist, check is checked or not
if (checklist_line_view_type === "checkbox") {
var checkboxValue = false;
if ($('#' + checklist_line_view_id).prop('checked') === true) {
checkboxValue = true;
} else {
checkboxValue = false;
}
if (checklist_line_view_id.match(/answer_yes_type/gi)) {
console.debug('Write on yes_type');
//call method that write the new value for checkbox
Checklists.call('write', [checklist_line_id_int, {answer_yes: checkboxValue}]
).then(function () {
//Call a method in backend that manage the subsections related to a section
Checklists.call('subsections_management_frontend', [checklist_line_id_int]).then(function () {
window.location.reload();
});
});
} else if (checklist_line_view_id.match(/answer_no_type/gi)) {
console.debug('Write on no_type');
//call method that write the new value for checkbox
Checklists.call('write', [checklist_line_id_int, {answer_no: checkboxValue}]
).then(function () {
//Reload full page
$('#container_lines').load(location.href + " #container_lines");
});
} else if (checklist_line_view_id.match(/answer_undecided_type/gi)) {
console.debug('Write on undecided_type');
//call method that write the new value for checkbox
Checklists.call('write', [checklist_line_id_int, {answer_undecided: checkboxValue}]
).then(function () {
//Reload
window.location.reload();
//$('#container_lines').load(location.href + " #container_lines");
});
}
} else if (checklist_line_view_type === "text") {
var value = $('#' + checklist_line_view_id).val();
if (checklist_line_view_id.match(/answer_text_type/gi)) {
console.debug('Write on answer_text_type');
//call method that write the new value for checkbox
Checklists.call('write', [checklist_line_id_int, {answer_text: value}]
).then(function () {
//Reload full page
window.location.reload();
});
}
} else if (checklist_line_view_type === "number") {
var value = $('#' + checklist_line_view_id).val();
if (checklist_line_view_id.match(/answer_value_type/gi)) {
console.debug('Write on answer_value_type');
//call method that write the new value for checkbox
Checklists.call('write', [checklist_line_id_int, {answer_value: value}]
).then(function () {
//Reload full page
window.location.reload();
});
}
}
}
//Intercept witch row and view is clicked
$('.section_line').on("change", "input, textarea", function () {
//Get row id of checklist
var checklist_line_id = $(this).parent().parent().attr('id');
//Get the id of clicked element
var checklist_line_view_id = $(this).attr('id');
//Get the type of clicked element
var checklist_line_view_type = $(this).attr('type');
console.debug('checklist_line_id: ' + checklist_line_id);
console.debug('checklist_line_view_id: ' + checklist_line_view_id);
console.debug('checklist_line_view_type: ' + checklist_line_view_type);
//Function that store the changed field
update_line_value(checklist_line_id, checklist_line_view_id, checklist_line_view_type);
});
//Intercept if the user click some Sections to add to checklist
$('.sectionAddRemove').on("click", function () {
setTimeout(function () {
window.location.reload();
//$('#container_lines').load(location.href + " #container_lines");
//$('#container_sections').load(location.href + " #container_sections");
}, 100);
//$('#container_lines').load(location.href + " #container_lines");
});
});
}
);
Where i'm wrong to do that?
My objective is to reload only the div that contain rows not all the page.
Founded the problem.
//Intercept witch row and view is clicked
$('.section_line').on("change", "input, textarea", function () {
//Get row id of checklist
var checklist_line_id = $(this).parent().parent().attr('id');
//Get the id of clicked element
var checklist_line_view_id = $(this).attr('id');
//Get the type of clicked element
var checklist_line_view_type = $(this).attr('type');
console.debug('checklist_line_id: ' + checklist_line_id);
console.debug('checklist_line_view_id: ' + checklist_line_view_id);
console.debug('checklist_line_view_type: ' + checklist_line_view_type);
//Function that store the changed field
update_line_value(checklist_line_id, checklist_line_view_id, checklist_line_view_type);
});
$('.section_line').on("change"... .section_line is inside the div $('#container_lines') so when the div get reloaded it's lost the handler.
Just change $('.section_line').on("change"... with $(document).on("change"... or an high container that contain the container_lines

How do I fire a function immediately after another function is finished?

I have the following code:
<script>
function refreshChat() {
var id = "'.$convers_id.'";
var receiver = "'.$system->getFirstName($second_user->full_name).'";
$.get("'.$system->getDomain().'/ajax/refreshChat.php?id="+id+"&receiver="+receiver, function(data) {
$(".conversation-content").html(data);
});
var scroller = $(".conversation-message-list").getNiceScroll(0);
$(".conversation-message-list").getNiceScroll(0).doScrollTop($(".conversation-content").height(),-1);
}
window.setInterval(function(){
refreshChat();
}, 2000);
function sendMessage() {
var user2 = "'.$user2.'";
var message = $("#message");
if(message.val() != "" && message.val() != " ") {
$.get("'.$system->getDomain().'/ajax/sendMessage.php?id="+user2+"&msg="+encodeURIComponent(message.val()), function(data) {
$(".conversation-content").html(data);
message.val("");
});
}
}
$(document).keypress(function(e) {
if(e.which == 13) {
sendMessage();
}
});
</script>
Right now, the refreshChat function calls an ajax script every 2 seconds. When you have entered a message and press enter, it calls a different ajax script. What I would like it to do, is call both functions at the same time. So the script calls the sendMessage function first and refreshes afterwards.
How can I do this? I have already tried changing it to:
<script>
function refreshChat() {
var id = "'.$convers_id.'";
var receiver = "'.$system->getFirstName($second_user->full_name).'";
$.get("'.$system->getDomain().'/ajax/refreshChat.php?id="+id+"&receiver="+receiver, function(data) {
$(".conversation-content").html(data);
});
var scroller = $(".conversation-message-list").getNiceScroll(0);
$(".conversation-message-list").getNiceScroll(0).doScrollTop($(".conversation-content").height(),-1);
}
function sendMessage() {
var user2 = "'.$user2.'";
var message = $("#message");
if(message.val() != "" && message.val() != " ") {
$.get("'.$system->getDomain().'/ajax/sendMessage.php?id="+user2+"&msg="+encodeURIComponent(message.val()), function(data) {
$(".conversation-content").html(data);
message.val("");
});
}
}
$(document).keypress(function(e) {
if(e.which == 13) {
sendMessage();refreshChat();
}
});
</script>
But this only enters the message first, and it only refreshes on the second keypress (enter). I would like to thank everybody beforehand on helping me out.
This is actually an illusion. Both functions are being called, but the chat window is refreshing before the chat message is able to save them.
To fix this, you should refresh the chat window only once the new message has been successfully saved:
function refreshChat() {
// Removed for brevity
}
function sendMessage() {
var user2 = "'.$user2.'";
var message = $("#message");
if(message.val() != "" && message.val() != " ") {
$.get("'.$system->getDomain().'/ajax/sendMessage.php?id="+user2+"&msg="+encodeURIComponent(message.val()), function(data) {
$(".conversation-content").html(data);
message.val("");
// Now, this will only be called once the ajax is complete
refreshChat();
});
}
}
$(document).keypress(function(e) {
if(e.which == 13) {
sendMessage();
// I removed the refreshChat() call from here and moved it
// into the $.get() callback above ^^
}
});
As you can see, I moved your refreshChat() method to now be called from within the jQuery $.get() callback.
Have you tried using callbacks, that may be what you need?
Here is a link for reference.
http://www.impressivewebs.com/callback-functions-javascript/
MY WORKING AWNSER
Considering for what i asked, i have marked Wes Foster's awnser as correct. What made it work for me is also applying a promises after the get function. This way, the ajax script get's called twice as needed. I hope it will help someone in the future. (Look at me... travelling through time...). You will find my code underneath:
function refreshChat() {
var id = "'.$convers_id.'";
var receiver = "'.$system->getFirstName($second_user->full_name).'";
$.get("'.$system->getDomain().'/ajax/refreshChat.php?id="+id+"&receiver="+receiver, function(data) {
$(".conversation-content").html(data);
});
var scroller = $(".conversation-message-list").getNiceScroll(0);
$(".conversation-message-list").getNiceScroll(0).doScrollTop($(".conversation-content").height(),-1);
}
function sendMessage() {
var user2 = "'.$user2.'";
var message = $("#message");
if(message.val() != "" && message.val() != " ") {
$.get("'.$system->getDomain().'/ajax/sendMessage.php?id="+user2+"&msg="+encodeURIComponent(message.val()), function(data) {
$(".conversation-content").html(data);
message.val("");
refreshChat();
}).done(refreshChat);
}
}
$(document).keypress(function(e) {
if(e.which == 13) {
sendMessage();
}
});

jQuery - preventDefault() in .each function

I want to use preventDefault() in .each function for collection of buttons and its not working. When I use it with one .click function it works fine but inside .each is not
Whan am I doing wrong?
Here is my .js code
$(document).ready(function() {
var findingStatus = $('#findingStatus').attr('finding-status-type');
var findingLike = $('#finding_like_btn');
var findingDislikeBox = $('.finding_dislike_add');
var findingDislikeCollection = $('.finding_dislike_add_btn')
var findingUnlike = $('#finding_unlike_btn');
var findingDislikeRemoved = $('#finding_dislike_removed');
var alertBox = $('.alert-box').hide();
if (findingStatus == 0) {
findingDislikeBox.show();
findingUnlike.hide();
findingDislikeRemoved.hide();
}
else if (findingStatus == 1) {
findingDislikeBox.hide();
findingUnlike.show();
findingDislikeRemoved.hide();
}
else if (findingStatus == 2) {
findingDislikeRemoved.show();
findingUnlike.show();
findingDislikeBox.hide();
findingLike.hide();
}
findingDislikeCollection.each(function() {
var findingDislike = $(this).clone();
var url = findingDislike.attr("href");
findingDislike.click(function(event) {
event.preventDefault();
$.ajax({
url: url,
type: "POST",
dataType: "json",
success: function(data) {
if (data.profileState == 1) {
$('#dislike_count_btn').text('Odrzuć' + data.DislikeCount);
findingDislikeBox.hide();
findingDislikeRemoved.show();
findingUnlike.show();
//findingUnDislike.show();
//findingUnDislike.attr('disabled', false );
//findingUnDislike.text('Cofnij');
}
else {
alertBox.show();
if ($('.alert-box-msg').length==0) {
$('.alert-area').prepend('<p class="alert-area alert-box-msg">Żeby korzystać z tej funkcji musisz być zalogowany.</p>');
}
findingDislike.attr('disabled', false );
}
},
error: function() {
alert('Problem z serwerem, spróbuj ponownie za kilka minut.');
findingDislike.attr('disabled', false );
}
});
});
});
$('html').click(function (e) {
if (!$(e.target).hasClass('alert-area')) {
$('.alert-box').hide();
findingDislike.attr('disabled', false );
}
});
});
Thanks for answer
You are cloning the element with .clone which means you're not actually attaching an event listener to anything in the DOM. Cloned elements must be manually inserted into the DOM with JavaScript for them to have any effect.
This is not a correct way. Following should work:
findingDislikeCollection.click(function(event){
var findingDislike = $(this);
var url = findingDislike.attr("href");
//AJAX call
event.preventDefault();
});
More details on click event are given here:
https://api.jquery.com/click/

ajax prevent double posting on mouseenter

Can someone point out what I need in my code to stop it doubling up on data when you mouseenter on the hyperlink tag. I put a flag in there isLoading but it still continues to double up. I've probably done it wrong could someone have a look through my code and see whats wrong with it - see if you can prevent it from double posting on mouseenter. Please show me you're changes - Thanks from KDM.
(function($){
$.fn.rating_display = function() {
var _this = this;
var id = $(_this).data('id');
var position = $(this).parent().position();
var left = position.left - 15;
var top = position.top + $(this).height() + 13;
var isLoading = false;
function clear_ratings() {
$('.ratings-content').html("");
}
$(document).on('click', function(e) {
var element = e.target;
/*else if($(element).closest('.rating').length){
$('.ratings-display').show();
}*/
});
// here is where I'm having trouble with double posting
$(this).on('mouseenter click', function(e) {
if(isLoading == true) return false;
$.ajax({
type:'POST',
dataType:"html",
data:{product_id:id},
url:"../../webservices/get_rating.php",
beforeSend: function() {
clear_ratings();
$('.ratings-display').show().css({'left':left + 'px', 'top':top + 'px'});
isLoading = true;
},
success: function(data) {
$('.ratings-content').append(data);
}, error:function(data, status, xhr) {
clear_ratings();
$('.ratings-content').html(data + "\r\n" + status + "\r\n" + xhr);
}
});
}).on('mouseleave', function(e) {
var target = e.relatedTarget;
if($(target).closest('.ratings-display').length) {
return false;
}else{
$('.ratings-display').hide();
clear_ratings();
isLoading = false;
}
});
$('.ratings-display').on('mouseleave',function (e) {
var target = e.relatedTarget;
if($(target).closest('.rating').length) return false;
if(!$(target).closest('.ratings-display').length) {
$('.ratings-display').hide();
clear_ratings();isLoading = false;
}
});
}
})(jQuery);
'mouseenter click' means the action is performed once at mouseenter and again if you click.
Try setting isLoading = true; before the ajax call rather than in the beforesend function. And you also want to reset isLoading = false on ajax call completion rather than on mouseleave. Depending on whether you're doing it for keyboard navigation reasons or not, you could also stop listening to the click event entirely.

Categories