0

So, I'm not great at jQuery, and I'm having some issues with functions that I want to reuse in different events.

Eg: I start off with one "feature" box, but I have a "+" button that will add additional boxes using jQuery.

I have 3 buttons underneath each box (up, down and delete) to reorder or delete the boxes (using jQuery .click())

With the reorder and delete functions, it seems that I need to include them both inside the "add feature" jQuery click event, as well as outside it (for the static initial feature). There are also some other things I want to do every time a feature is added, deleted or reordered (eg: make the top "up" arrow and bottom "down" arrow disabled).

So I tried some functions and seem to have made a real mess of things. Eg: if I add 2 extra features, then delete Feature 2, it calls the delete dialogue twice. Mo features = mo dialogues. Same issues for moving up and down, skips all over the place!

I don't understand how I can have 'reusable' functions without these side-effects, can anyone point me in the right direction?

$(document).ready(function() {

function toggleFeatureArrows(){
  var fCount = $(".featured-category").length;
  $(".featured-category").each(function(i){
   var x = i + 1;
   if(x == 1){
    $(this).find(".feature-up").addClass("disabled");
   }
   if(fCount > 1 && x > 1){
    $(this).find(".feature-up").removeClass("disabled");
   }
   if(fCount > 1 && x < fCount){
    $(this).find(".feature-down").removeClass("disabled");
   }
   if(x == fCount){
    $(this).find(".feature-down").addClass("disabled");
   }
  });
 }

 function moveFeatures(){
  $(".feature-up").click(function(){
   console.log("Clicked up!");
     var $current = $(this).closest('div.featured-category')
     var $previous = $current.prev('div.featured-category');
     if($previous.length !== 0){
       $current.insertBefore($previous);
       // switch orders
       var currentOrder = $current.find('.feature-order').val();
    var prevOrder = $previous.find('.feature-order').val();
    $current.find('.feature-order').val(prevOrder);
    $previous.find('.feature-order').val(currentOrder);

    toggleFeatureArrows();
     }
     return false;
  });

  $(".feature-down").click(function(){
   console.log("Clicked down!!");
     var $current = $(this).closest('div.featured-category')
     var $next = $current.next('div.featured-category');
     if($next.length !== 0){
       $current.insertAfter($next);
       // switch orders
       var currentOrder = $current.find('.feature-order').val();
    var nextOrder = $next.find('.feature-order').val();
    $current.find('.feature-order').val(nextOrder);
    $next.find('.feature-order').val(currentOrder);

    toggleFeatureArrows();
     }
     return false;
  });     
 }

 // Delete features
 function deleteFeature(){
  $(".feature-delete").click(function(){
   console.log(" Deleting feature id: " + featureID);
   if(confirm('Are you sure you want to delete this feature?')){
    // get the feature id
    var $current = $(this).closest('div.featured-category');
    var featureID = $current.find(".feature-id").val();

      if(featureID > 0){
       // do some ajax
       // 
       // if success remove current
            $current.remove();
      }
      else {
       $current.remove();
      }
      // reorder
      $(".featured-category").each(function(i){
       var x = i + 1;
       $(this).find(".feature-order").val(x);
      });
      toggleFeatureArrows();
   }   
  });
 }

 // Move features
 moveFeatures();  

 // Delete features
 deleteFeature();

 // ADD FEATURED BLOCK
 $("#addFeature").click(function(){
  
  var fCount = $(".featured-category").length + 1;
  
  var fContent = '<div class="featured-category"><div class="row"><div class="col-xs-2">F' + fCount + '</div><div class="col-xs-10">' +
    '<input type="hidden" name="featured['+ (fCount - 1) +'][id]" class="feature-id" value="">' + 
    '<input type="text" name="featured['+ (fCount - 1) +'][order]" value="'+ fCount +'" class="feature-order"></div></div>' +
    
    '<div class="row"><div class="col-xs-2">F' + fCount + ' Description</div><div class="col-xs-10"><textarea name="featured['+ (fCount - 1) +'][description]" rows="5" class="form-control"></textarea></div></div>' +
    
   '<div class="row"><div class="col-xs-2"></div><div class="col-xs-10">' +
   '<div class="alert alert-warning">' +
   '<button type="button" class="btn btn-default btn-sm feature-delete" title="Delete"><i class="fa fa-trash"></i>delete</button> ' +
   '<button type="button" class="btn btn-default btn-sm feature-up disabled" title="Move up"><i class="fa fa-arrow-up"></i>up</button> ' +
   '<button type="button" class="btn btn-default btn-sm feature-down disabled" title="Move down"><i class="fa fa-arrow-down">down</i></button>' +
   '</div></div></div><br>';

  $("#features").append(fContent);

  toggleFeatureArrows();     

  // Move features
  moveFeatures();

  // Delete function
  deleteFeature();
 });
     
});
   
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="features">
  <div class="row">
    <div class="col-xs-2">Heading</div>
    <div class="col-xs-10">
      <input name="featured-heading" type="text" class="form-control"  placeholder="Featured XXXXXX products" value="">
    </div>
  </div>
  <div class="featured-category">
    <div class="row">
      <div class="col-xs-12"><hr></div>
    </div>
    <div class="row">
      <div class="col-xs-2">F1</div>
      <div class="col-xs-10">
        <input type="hidden" name="featured[0][id]" value="" class="feature-id">
        <input type="text" name="featured[0][order]" value="1" class="feature-order">
      </div>      
    </div>
    <div class="row">
      <div class="col-xs-2">F1 Description</div>
      <div class="col-xs-10">
        <textarea name="featured[0][description]" id="" rows="5" class="form-control"></textarea>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2"></div>
      <div class="col-xs-10">
        <div class="alert alert-warning">
          <button type="button" class="btn btn-default btn-sm feature-delete" title="Delete"><i class="fa fa-trash"></i>delete</button>
          <button type="button" class="btn btn-default btn-sm feature-up disabled" title="Move up"><i class="fa fa-arrow-up"></i> up</button> 
          <button type="button" class="btn btn-default btn-sm feature-down disabled" title="Move down"><i class="fa fa-arrow-down"></i> down</button>
        </div>
   </div>
    </div>
   <br>
  </div>
</div>
<button type="button" class="btn btn-success" id="addFeature">+</button>

`

Sanfly
  • 1,021
  • 1
  • 11
  • 19
  • You are creating new bindings inside the `moveFeatures` and `deleteFeature` functions. And you are doing so on off of the results of a global lookups; `$(".feature-up")`, `$(".feature-down")`, `$(".feature-delete")`. This is the source of your multiple executions. Every time you create new bindings, such as when you add a new feature, you are creating duplicate bindings on those that already existed. I would highly suggest you take a look at creating delegate bindings instead, that will help alleviate this issue. – Taplar Mar 19 '18 at 15:28
  • Thanks thats perfect, I didn't even really know what event binding was - learning more every day! – Sanfly Mar 19 '18 at 20:55

0 Answers0