JQuery with ajax keeps posting multiple results - javascript

I have many images on a page that show the status of the machine. If you click on the image then modal window opens and you can select new status. Status gets send via ajax to the DB. If I try to change another machines status the previous machines status gets changed also. Every status that I have touched gets resend every time as the last status that I selected.
It somehow creates an array of the machines I have changed and with every change posts all of them. Refresh of the page empties the array.
I think I need to use something similar to unset in php or move the inner click function outside of the first click function.
$(function() {
$('#mach_status_dialog').hide();
$('.mach_status').click(function(){
var mach = $(this).attr('id');
$('#mach_status_dialog').dialog({
modal: true,
draggable: false,
resizable: false,
width: 500,
title: 'Mach ' + mach + ' status'
});
$('.statuses').click(function(){
var user = user;
var class = $(this).attr('class');
class = class.substring(10);
var status = $(this).first().find('p').parent().text();
var data_string = 'mach=' + mach + '&status=' + status + '&user=' + user;
$.ajax({
url: 'ajax_op_mach_status.php',
type:'POST',
data: data_string,
dataType: 'json',
cache: false,
success: function(response){
var newSrc = 'images/Circle2_'+class+'_25.png';
console.log($('#'+mach+'.mach_status').attr('src', newSrc));
$('#'+mach+'.mach_status').attr('src', newSrc);
$('#'+mach+'.mach_status').attr('title', status);
$( "#mach_status_dialog" ).dialog('close');
}
});
});
});
});

$(function() {
$('#mach_status_dialog').hide();
$('.mach_status').click(function(){
var mach = $(this).attr('id');
$('#mach_status_dialog').dialog({
modal: true,
draggable: false,
resizable: false,
width: 500,
title: 'Mach ' + mach + ' status'
});
});
$(document).on('click', '.statuses', function(){
var user = user;
var class = $(this).attr('class');
class = class.substring(10);
var status = $(this).first().find('p').parent().text();
var data_string = 'mach=' + mach + '&status=' + status + '&user=' + user;
$.ajax({
url: 'ajax_op_mach_status.php',
type:'POST',
data: data_string,
dataType: 'json',
cache: false,
success: function(response){
var newSrc = 'images/Circle2_'+class+'_25.png';
console.log($('#'+mach+'.mach_status').attr('src', newSrc));
$('#'+mach+'.mach_status').attr('src', newSrc);
$('#'+mach+'.mach_status').attr('title', status);
$( "#mach_status_dialog" ).dialog('close');
}
});
});
});

As you say, just move the .click event into the DOM ready callback. As it stands, every time you click on a mach_status, you are assigning a new click event handler. So if I click on mach_status 10 times, then click on a statuses link once, you'll get 10 AJAX requests.
If you only want to bind onto a statuses click when the user clicks on mach_status, add a class onto the element to tell it when it's ready:
$(function() {
$('#mach_status_dialog').hide();
$('.mach_status').click(function(){
$(".statuses").addClass("ready");
var mach = $(this).attr('id');
$('#mach_status_dialog').dialog({
modal: true,
draggable: false,
resizable: false,
width: 500,
title: 'Mach ' + mach + ' status'
});
});
$('.statuses.ready').click(function(){
// Do AJAX
});
});

The problem is here...
$('.statuses').click(function(){
Every time you click on *.mach_status* element, it adds the event listener for all the statuses. You can changes this to
$(this).find('.statuses').click(function abc(){
.
.
.
this.removeEventListner('click', abc);
});
Notice How I am using the named functions and removing them from event queue once they are fired.

Related

Javascript looping nested click event

I have a nested click event listeners and I have a problem, that when I trigger the event listeners multiple times they get looped and send a request x2 times than it should. Where is the mistake in my code? It's probably a beginner's mistake, so I'm very sorry if that's the case. I'm still learning JavaScript and jQuery.
Code:
$('body').on('click', '.color-pick-btn', function() {
id = $(this).data("highlight");
unique = $(this).data("unique");
$(".color-picker").show();
//show the menu directly over the placeholder
$(".color-picker").position({
my: "right top",
at: "right bottom",
of: this,
collision: "fit"
});
$('body').on('click', '.color-picker-item', function() {
color = $(this).data("color");
$.ajax({
type: "POST",
url: '/echo/json',
//data: "highlight=" + id + '&color=' + color + "&unique=" + unique,
data: {
json:'{"highlight":"id","color":"color","unique": "unique"}'
},
dataType: 'json',
}).done(function(data) {
console.log('test');
});
$(".color-picker").hide();
return false;
});
$(document).click(function(event) {
if (!(($(event.target).hasClass('color-pick-btn')) || ($(event.target).hasClass('color-picker-item')))) {
$(".color-picker").hide();
}
return false;
});
return false;
});
JSFiddle here: https://jsfiddle.net/o0r4z6g3/
Check out the console output "test".
Cheers!
You added event listeners every time your event listener was called. I haven't taken a look at the intention of your code, and you haven't explained it in your answer, but this may fix your problem.
$('body').on('click', '.color-pick-btn', function() {
// .position() uses position relative to the offset parent,
// so it supports position: relative parent elements
pos = $(this).offset();
id = $(this).data("highlight");
unique = $(this).data("unique");
// .outerWidth() takes into account border and padding.
width = $(this).outerWidth();
$(".color-picker").show();
//show the menu directly over the placeholder
$(".color-picker").position({
my: "right top",
at: "right bottom",
of: this,
collision: "fit"
});
return false;
});
$('body').on('click', '.color-picker-item', function() {
color = $(this).data("color");
$.ajax({
type: "POST",
url: '/echo/json',
//data: "highlight=" + id + '&color=' + color + "&unique=" + unique,
data: {
json: '{"highlight":"id","color":"color","unique": "unique"}'
},
dataType: 'json',
}).done(function(data) {
console.log('test');
});
$(".color-picker").hide();
return false;
});
$(document).click(function(event) {
if (!(($(event.target).hasClass('color-pick-btn')) || ($(event.target).hasClass('color-picker-item')))) {
$(".color-picker").hide();
}
return false;
});

jQuery dialog can not call second time

IE v11 on windows 10 using jQuery v2.2.2 and jQuery-ui v1.10.0
Can't get a dialog to open a second time. I was having trouble getting the ok button to close the dialog and solved that by getting a reference to the dialog with the 'PDdialog = '. Now on the second attempt I get error: Object doesn't support property or method 'dialog'. I even tried adding the .remove() in the Ok function.
$( document ).ready(function() {
$.ajaxSetup({ cache: false });
$( ".pnopener" ).on( "click", function() {
var pn = $(this).text();
var tag = $("<div id='pd-dialog' title='PN Details'></div>");
$.ajax({
type: "GET",
url: 'ajax/PNDetails.php?pn=' + pn ,
success: function (data) {
PDdialog = tag.html(data).dialog({
resizable: true,
height: 600,
width: 750,
modal: true,
buttons: {
Ok: function() {
PDdialog.dialog( "close" );
$( ".pd-dialog" ).remove();
}
}
}).dialog('open');
}
});
});
});
and just for clarity here is the calling html:
<span class="pnopener" style="color: darkorange;">[Changing string]</span>
This is in a table td.
more:
In Firefox the error is: TypeError: tag.html(...).dialog is not a function
Thanks!!

Jquery Ajax simple application: missing ) after argument list

I'm pulling my hair out here. I keep getting "missing ) after argument list" on my final line of code. I'm thinking it has something to do with my concatenation but I can't figure it out. It's jQuery with jQuery UI: a simple slider. User increases the amount on the slider and the available flights at that amount are displayed. Clicking on the available flight shows the duration:
$(document.ready(function(){
$.ajax({
url: 'http://localhost:8888/all_work_july_6/javascript_start_here/flights.php',
dataType: "json",
success: function(data){
var counter = 0;
$.each(data, function(key, value){
$("#flightList").append('<li ' + 'id="flight' + counter + '"' + ' class="flightLi">' + value['trip'] + '<span class="hiddenPrice">' + value['price'] + '</span></li>');
counter++;
});
}
});
$("#priceSlider").slider({
orientation: "vertical",
min: 200,
max: 1650,
step: 200,
value: 1650,
slide: function(event, uiElement){
$("#flightDetails").html("<p>Flight Details</p>").addClass("hidden");
var numRegex = /(\d+)(\d{3})/;
var inputNum = uiElement.value;
var strNum = inputNum.toString();
strNum = strNum.replace(numRegex, '$1' + ',' + '$2');
$("#spanPrice").text(strNum);
$("#inputPrice").val(uiElement.value);
$(".hiddenPrice").each(function(){
if($(this).text() > inputNum){
$(this).parent().addClass("hidden");
}
else if($(this).text() < inputNum){
$(this).parent().removeClass("hidden");
}
});
}
});
$(".flightLi").on('click', function(){
$("#flightDetails").html("<p>Flight Details</p>").addClass("hidden");
var myId = $(this).attr("id");
$.ajax({
url: 'http://localhost:8888/all_work_july_6/javascript_start_here/details.php',
dataType: "json",
data: { "flightID": myId },
type: "POST",
success: function(data) {
$("#flightDetails").removeClass("hidden").append('<ul>' + '<li class="detailsLi">Trip Duration: ' + data['duration'] + '</li>' + '</ul>');
}
});
});
});
The problem was in the first line, Missing ) in $(document
//$(document.ready(function(){ You had this. ) is missing
$(document).ready(function(){
 Missing )in $(document
Replace $(document to $(document)
Here is a live demo
$(document).ready(function() {
// mocked response from flights.php
var data = {
json: $.toJSON({0: {trip: "Hawaii", price: "1000"} }),
delay: 3
}
// AJAX post to "fllights.php" and process the response
$.ajax({
url:"/echo/json/", // JSfiddle Echo API - http://doc.jsfiddle.net/use/echo.html
data:data,
type:"POST",
success:function(data){
var counter = 0;
$.each(data, function(key, value){
var li = "<li id='flight"+counter+"'"+" class='flightLi'>"+value['trip']+"<span class='hiddenPrice'>"+value['price']+"</span></li>";
$('#flightList').append(li);
addListener(); // add the onClick listener to the newly created <li> item.
counter++; // You could also pass in the id attribute to this method
});
}
});
// Slider
$("#priceSlider").slider({
orientation: "vertical",
min: 200,
max: 1650,
step: 200,
value: 1650,
slide: function(event, uiElement){
$("#flightDetails").html("<p>Flight Details</p>").addClass("hidden");
var numRegex = /(\d+)(\d{3})/;
var inputNum = uiElement.value;
var strNum = inputNum.toString();
strNum = strNum.replace(numRegex, '$1' + ',' + '$2');
$("#spanPrice").text(strNum);
$("#inputPrice").val(uiElement.value);
$(".hiddenPrice").each(function(){
if($(this).text() > inputNum){
$(this).parent().addClass("hidden");
}
else if($(this).text() < inputNum){
$(this).parent().removeClass("hidden");
}
});
}
});
// moked response from details.php for "flightID": myId
data = {
json: $.toJSON({duration: '1000 hrs'}),
delay: 1
}
// wraper method to only add the onClick listner after the new <li> is inserted to the DOM
function addListener(){
// List item onClick AJAX
$(".flightLi").one( "click", function() { // Using the .one method to only add the onClick event listener once
$("#flightDetails").html("<p>Flight Details</p>").addClass("hidden");
console.log("Flight id: "+$(this).attr("id"));
$.ajax({
url:"/echo/json/",
dataType: "json",
data: data,
type: "POST",
success: function(data) {
var li = "<ul><li class='detailsLi'>Trip Duration: "+data['duration']+"</li></ul>";
$("#flightDetails").removeClass("hidden").append(li);
}
});
});
}
// Origional code
// This doesn't work due to the fact that the <li> item
// in the flightList list is inserted to the the DOM after the intital load
// you can also bind the event at the document level see this post http://bit.ly/1S0H2q0
// $(".flightLi").on('click', function(){
// $("#flightDetails").html("<p>Flight Details</p>").addClass("hidden");
// console.log("Flight id: "+$(this).attr("id"));
// $.ajax({
// url:"/echo/json/",
// dataType: "json",
// data: data,
// type: "POST",
// success: function(data) {
// var li = "<ul><li class='detailsLi'>Trip Duration: "+data['duration']+"</li></ul>";
// $("#flightDetails").removeClass("hidden").append(li);
// }
// });
// });
});
A few things I noticed while going through your code:
The $("#flightDetails").html("<p>Flight Details</p>").addClass("hidden"); line is actually removing the Trip Duration: content because it completely replaces the html inside of the #flightDetails element. - This might be intentional
Adding the onClick event listener to the newly created <li> elements must be done at the document level, or from inside of the call back that actually injects them into the DOM. I chose to implement the call back method. See this post for adding the listener at the document level
Adding the event listener from inside of the call back method opens up the issue of possibly adding the event listener to the same element multiple times. This can result in an onClick event firing multiple times per one trigger. Again you must either add the event at the document level, or use the one method to only add the event once. See the JQuery.one documentation

Bootstrap Popover not working consistently

I have a problem with the bootstrap Popover. It works sometime but other times it doesn't. I use it to generate a popover with a users information when a visitor hovers over the users name. The page is generated by ajax so at first I thought that it simply was an issue of content being loaded after but the issue is that it works sometimes.
$(document).on('mouseenter', '.postusername', function(e){
var userid = this.parentElement.parentElement.children[0].innerHTML;
var te = this;
if(userid)
{
$.get('/Requests/getuinfo.php', {id : userid})
.done(function(data){
var uinfo = JSON.parse(data);
boo = uinfo;
$(te).popover({
html : true,
template : '<div class="popover" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>',
content : '<div class="popover-holder" style="background-image:url(\'/Style/Media/CoverPics/' + uinfo.coverpic + '\');">' + uinfo.name
+ '</div>',
placement: 'auto'
});
$(te).popover('show');
});
}
});
$(document).on('mouseleave', '.postusername', function(e){
$(this).popover('hide');
});
That is the Javascript I used.
As you've found, the problem was the fact that you were trying to create a new popover for something when it had already been done. Removing the popover after hiding it has fixed that problem.
However, this should fix the problem without removing it, and will mean you will also only get user information once per user...
var userids = [];
$(document).on('mouseenter', '.postusername', function(e){
var userid = this.parentElement.parentElement.children[0].innerHTML;
var te = this;
if(userid)
{
if (userids.indexOf(userid) === -1) {
$.get('/Requests/getuinfo.php', {id : userid})
.done(function(data){
var uinfo = JSON.parse(data);
boo = uinfo;
$(te).popover({
html : true,
template : '<div class="popover" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>',
content : '<div class="popover-holder" style="background-image:url(\'/Style/Media/CoverPics/' + uinfo.coverpic + '\');">' + uinfo.name
+ '</div>',
placement: 'auto'
});
$(te).popover('show');
userids.push(userid);
});
}
else {
$(te).popover('show');
}
}
});
$(document).on('mouseleave', '.postusername', function(e){
$(this).popover('hide');
});
It keeps an array of the user ids that you've got info for, and only gets the info if you've not already done it.

Redirect parent window from within Jquery modal UI

I load a Jquery Modal UI with the following code:
// Dialog
$('#avatar-manager').click(function () {
$dialog.dialog('open');
return false;
});
var $dialog = $('<div></div>')
.dialog({
autoOpen: false,
resizeable: false,
modal: true,
title: 'Change your avatar...',
position: 'top',
width: 600,
open: function () {
$(this).load('/components/avatar/avatar.aspx?id=<%=Helpers.CurrentUserId(Session["SessionHash"].ToString())%>&type=user');
}
});
$dialog.parent().appendTo(jQuery("form:first"));
All works well. The avatar.aspx page has the code on an a to complete the process:
$('#go').live('click', function () {
$('#croppanel').hide();
$('#loadingpanel').show();
$.ajax({
type: "POST",
url: "http://<%=Atomic.UI.Helpers.CurrentServer()%>/AtomicService/Assets.asmx/CreateAvatar",
data: "{'avatarPath':'" + file_path + "','type':'user', 'w':'" + $('#<%=w.ClientID%>').val() + "','h':'" + $('#<%=h.ClientID%>').val() + "','x':'" + $('#<%=x.ClientID%>').val() + "','y':'" + $('#<%=y.ClientID%>').val() + "'}",
contentType: "application/json",
dataType: "json",
success: function (msg) {
if (msg["d"].length > 0) {
//done
//$dialog.dialog('close');
var cachekiller = Math.floor(Math.random() * 1000);
>>>>
}
},
error: function (msg) {
alert("Unfortunately, we can't upload that image now. Why not try again?");
$('#loadingpanel').hide();
$('#croppanel').show();
}
});
I would like to redirect or close the modal where the >>>>'s are. How can I do this? I know $(this).dialog can't access the modal because of context, but I'm at a loss how to close from within the window. Remembering this a completely seperate page to where the dialog instantiation is done.
Help, suggestions and questions appreciated :)
Although my question perhaps didn't read that a really simple solution was required, it turned out that all I needed was:
setTimeout(window.location.reload(true), 3000);
Worked a treat :)

Categories

Resources