views:

72

answers:

2

I have tried to document this as well as I can in the code.

Getting a weird looping thing when I try to delete an item that I've added.

Example:

I have 3 items that I've added:

  • When I try to delete the very first item in the list...I get the confirm Delete dialog 3 times

  • Deleting the second item in the list...I get the confirm 2 times.

  • And yep...you guessed it..that last one gives it to me only once.

Thanks in advance.

Anyway, here's the commented jQuery code (it's a big one):

$(document).ready(function() {

  //hides the message/error console
  $("#console").hide();

//this is the add new button functionality  
  $("#save").click(function(){
    var ul = $("ul.addul");
    var addM = $(".mo").val();
    var addY = $(".yr").val();
    var addC = $(".ct").val();
    var addT = $("textarea#addThoughts").val();

    //submit the add
    $.post("save.php", { month : addM, year : addY, cottage : addC, thoughts : addT },
      function(data){

        //all good
        if(data.success) {

          //returns the item's respective id from db
          var returnID = data.id;

          //resets the form after items inserted into db
          document.getElementById('items').reset();

          //this puts the added item into the html
          $(".added").append(//content in here removed to shorten the example);

          //not implemented yet
          $(".edit").click(function(){
            $(this).parent().siblings("li.addit").hide();
            $(this).parent().siblings("li").children("[name=month], [name=year], [name=cottage], [name=thoughts]").show();
            $(this).parent().siblings("li").children(".showDataMonth, .showDataYear, .showDataCottage, .showDataThoughts").hide();
            $(this).siblings(".del").hide();
            $(this).siblings(".cancel, .save").show();
            $(this).hide();
          });

          //this is functioning properly; this cancels an update
          $("button.cancel").click(function(){
            $(this).parent().siblings("li.addit").show();
            $(this).parent().siblings("li").children("[name=month], [name=year], [name=cottage], [name=thoughts]").hide();
            $(this).parent().siblings("li").children(".showDataMonth, .showDataYear, .showDataCottage, .showDataThoughts").show();
            $(this).siblings(".edit, .del").show();
            $(this).siblings(".save").hide();
            $(this).hide();
          });

          //resetting of values to prepare another entry
          $(".save, .cancel, .month, .year, .cottage, .thoughts").hide();
          $(".showDataThoughts").css({ width : "160px;"});
          $(".mo, .yr, .ct").val("0");

          //shows successful insert of data into db
          $("#console").html(data.message).css({background: "green", color: "white"}).fadeIn().animate({ opacity : "+=0" }, 2000).fadeOut();

          //this is the delete function that I am referring to.
          //I get the "confirm" dialog just fine.
          //say I have 3 entries:
          //if I try to delete the first entry...I get the confirm delete dialog 3 times.
          //if I try to delete the second entry...I get the confirm delete dialog 2 times.
          //and the 3rd entry...I only get it once.
          //I'm stuck in a weird kinda loop.
          $(".del").click(function(){
              var del = this;
              var thisVal = $(del).val();
              $.post("delete.php", { dirID : thisVal },
              function(data){
                if(confirm("Are you sure you want to DELETE this entry?") == true) {
                  if(data.success) {
                    alert(thisVal);
                  }
                }
              return false;
              }, "json");
          });

        } else if(data.error) { //item could not be added
          $("#console").html(data.message).css({background: "red", color: "white"}).fadeIn().animate({ opacity : "+=0" }, 2000).fadeOut();
        }
    }, "json");
    return false;
}); //end of add button

//this populates the select boxes
$.getJSON('dates_in_residence.php', function(data){
    var htmlMonth = '';
    var htmlYear = '';
    var htmlCottage = '';
    var len = data.length;
    for (var i = 0; i < 12; i++) {htmlMonth += '<option class="optionMonth" value="' + data[i].month + '">' + data[i].month + '</option>';
    }
    $('select#addMonth').append(htmlMonth);
    for (var i = 12; i < 34; i++) {htmlYear += '<option class="optionYear" value="' + data[i].year + '">' + data[i].year + '</option>';
    }
    $('select#addYear').append(htmlYear);
    for (var i = 35; i < 42; i++) {htmlCottage += '<option class="optionCottage" value="' + data[i].cottage + '">' + data[i].cottage + '</option>';
    }
    $('select#addCottage').append(htmlCottage);
});

//this adds select menu's value to hidden inputs
$("#addMonth").change(function () {
          var str = '';
          $("#addMonth option:selected").each(function () {
                str += $(this).text() + " ";
              });
          $(".mo").val(str);
        }).change();
$("#addYear").change(function () {
          var str = "";
          $("#addYear option:selected").each(function () {
                str += $(this).text() + " ";
              });
          $(".yr").val(str);
        }).change();
$("#addCottage").change(function () {
          var str = "";
          $("#addCottage option:selected").each(function () {
                str += $(this).text() + " ";
              });
          $(".ct").val(str);
        }).change();
});

And the delete.php file:

<?php

if($_POST) {

  $data['delID'] = $_POST['dirID'];

  $query = "DELETE from //tablename WHERE dirID = '{$data['delID']}' LIMIT 1";

  $result = $db->query($query);

  if($result) {
    $data['success'] = true;
    $data['message'] = "This entry was successfully removed.";
  }

  echo json_encode($data);
}

?>
+1  A: 

The line:

$(".del").click(function(){

is returning all the elements with a class of del which means every time you add a new item you're adding a new event to each existing del element. (Glancing at the rest of your code this is going to be an issue for most of your elements apparently).

Your best option is to assemble the elements that make up each new item individually and assign specific events to them before appending them to the content. That way you know each specific element will have a single correct even associated with it.

EDIT:

passing data to a new function:

  $("#save").click(function(){
    var ul = $("ul.addul");
    var addM = $(".mo").val();
    var addY = $(".yr").val();
    var addC = $(".ct").val();
    var addT = $("textarea#addThoughts").val();

    //submit the add
    $.post("save.php", { month : addM, year : addY, cottage : addC, thoughts : addT },
      function(data){

        //all good
          if(data.success) {
            run_success(data);
          }
       }//close function
   }//close #save click

   //new, global function
   function run_success(data) {
       //do things with data here
   }

Setting up a global variable:

  $("#save").click(function(){
    var ul = $("ul.addul");
    var addM = $(".mo").val();
    var addY = $(".yr").val();
    var addC = $(".ct").val();
    var addT = $("textarea#addThoughts").val();

    //submit the add
    $.post("save.php", { month : addM, year : addY, cottage : addC, thoughts : addT },
      function(data){

        //all good
          if(data.success) {
            my_global_var = data; //note, my_global_var is created without a var
                                  //before it, thereby assigning it a global scope
          }
       }//close function
   }//close #save click
Steerpike
Is it possible to move the "delete", and "edit" functions out of the "save" function?
Scott
That wont fix the problem I'm afraid - you need to rewrite it so that the click events are attached to specific elements, not to a list of objects returned by a class selector
Steerpike
Is there any way to pull the "data" values out of the "save" function? To use elsewhere? Thanks.
Scott
You could pass it as an argument to another function or you could just set assign it to a global variable (any variable without a var keyword or one assigned at the window scope) if you're feeling incredibly lazy.
Steerpike
Could you show a small example of how I could get that data out? sorry I'm a total noob. Doesn't really have to be relevant to the code I have...just a small example of how you assign a global variable in jQuery.
Scott
Why do you need to pull the data out of the save function? Just doing that alone wont fix the problem I mentioned. Do you want to do it for a seperate issue, or are we having a discussion to try and fix an issue that I haven't explained clearly and you've misunderstood?
Steerpike
No...you've explained rather well actually. I was just hoping avoid a major overhaul. Thanks for all your help.
Scott
No prob, added examples for defining a global variable and passing data to a new function
Steerpike
Many thanks to you.
Scott
+1 for your help!
Scott
+1  A: 

I think you want to look at the live function in jQuery 1.3, which automatically binds events to newly-created elements. You'll need to move it completely out of the post section so that it runs on the first page load. Something like this should work:

$(".del").live("click", function(){
  //event code here
});
DisgruntledGoat
I was wondering about the "live" function...I'll give a try. Thanks!
Scott
Totally worked like a charm! Thanks so much.
Scott
I knew there had to be a way of moving that "delete" function outta the "save" function. Perfect!
Scott