breezy
breezy

Reputation: 1918

How to change counter/length when removing element from the dom

I am working on a widget which has a 'saved' and 'completed' module. When i remove the element it removes/fades it out from the dom but when I mark it as done it clones it to the completed tab. This is working awesome but the numbers inside the top parenthesis are not adjusting for me. What is a better way of doing this? I may be over thinking this.

I am using length to capture the amount of div's inside the parent. This is working good. But when i fadeout (remove) an element from the dom the counter/length doesn't change. Nor when I clone the element to the completed tab.

Here is a jsfiddle file I have set up.

http://jsfiddle.net/breezy/jvdnbw4q/

Here is my jQuery

$(document).foundation();

    $('.removed-saved-tip').click(function(e){
        $(this).closest('.saved-tip').fadeOut();
        e.preventDefault();
    });

    $('.saved-tip-done').click(function(e){

        $(this).toggleClass('marked-done');
        e.preventDefault();
        $(this).closest('.saved-tip').clone().appendTo('#panel2');
    });

    $('#panel1').each(function() { 

        var n = $(this).children('.saved-tip').length;
        $(".tab-title:first a").text("Saved (" + n + ")");

    });


    $('#panel2').each(function() { 

        var n = $(this).children('.saved-tip').length;
        $(".tab-title:last a").text("Completed (" + n + ")");

    });

Upvotes: 0

Views: 496

Answers (3)

Etheryte
Etheryte

Reputation: 25310

If you're going to move forward working with the project, it would probably be more reasonable to move to a specific MVVM (or MV*) framework and avoid manual DOM manipulation altogether.

Below is a simple example using Vue.js, but you could use more or less anything - the idea is to reduce manual labor and focus on the functionality.
Note how the code doesn't include any DOM manipulation, that's left entirely for the framework to handle.

var v = new Vue({
  el: 'body',
  data: {
    items: []
  },
  computed: {
    doneItems: function() {
      return this.items.filter(function(item) {
        return item.done;
      });
    }
  },
  methods: {
    addItem: function() {
      var value = ("" || this.input).trim();
      if (!value.length) return;
      this.items.push({
        title: value,
        done: false
      });
      this.input = '';
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.12/vue.min.js"></script>
<input autofocus placeholder="Add a new item" v-model="input" v-on="keyup:addItem | key 'enter'">
<p>All items ({{items.length}}):</p>
<ul v-repeat="items">
  <li>{{title}}
    <input type="checkbox" v-model="done" />
  </li>
</ul>
<p>Done items({{doneItems.length}}):</p>
<ul v-repeat="doneItems">
  <li>{{title}}
    <input type="checkbox" v-model="done" />
  </li>
</ul>

Upvotes: 0

Selvakumar Arumugam
Selvakumar Arumugam

Reputation: 79830

You need to call the count logic inside of the event handler for mark and remove.

// Tabs
$(document).foundation();

$('.removed-saved-tip').click(function (e) {
    $(this).closest('.saved-tip').addClass('removed').fadeOut();
    e.preventDefault();
    updateCount();
});

$('.saved-tip-done').click(function (e) {
    $(this).toggleClass('marked-done');
    e.preventDefault();
    $(this).closest('.saved-tip').clone().appendTo('#panel2');
    updateCount();
});

updateCount();
function updateCount() {
    $('#panel1').each(function () {
        var n = $(this).children('.saved-tip').filter(function() {
            return !$(this).hasClass('removed');
        }).length;
        $(".tab-title:first a").text("Saved (" + n + ")");
    });

    $('#panel2').each(function () {
        var n = $(this).children('.saved-tip').filter(function() {
            return !$(this).hasClass('removed');
        }).length;
        $(".tab-title:last a").text("Completed (" + n + ")");
    });
}
.tabs-content {
  margin: 10px auto 0 auto;
}
.tabs-content .content {
  background: #fff;
}
.print-option {
  background: #fbf7cc;
  padding: 5px 15px;
  margin: 0;
}
.print-option h4 {
  font-size: 14px;
}
.saved-tip {
  padding: 10px 15px;
  overflow: hidden;
  cursor: pointer;
}
.saved-tip:hover {
  background: #efefef;
}
.saved-tip .saved-tip-icon {
  float: left;
  margin: 0 10px 0 0;
}
.saved-tip h5 {
  color: #107CB2;
  font-size: 13px;
  float: left;
}
.saved-tip .saved-tip-options {
  float: right;
}
.saved-tip .saved-tip-options a {
  color: #676767;
  padding: 0 5px;
  border: 1px solid #dedede;
  border-radius: 3px;
  display: inline-block;
}
.saved-tip .saved-tip-options i {
  font-size: 14px;
}
.saved-tip a.marked-done {
  color: #107CB2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.2/js/foundation/foundation.tab.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.2/js/foundation.min.js"></script>
<link rel="stylesheet" href="http://cdn.foundation5.zurb.com/foundation.css" />

<ul class="tabs" data-tab>
  <li class="tab-title active"><a href="#panel1">Saved</a>
  </li>
  <li class="tab-title"><a href="#panel2">Completed</a>
  </li>
</ul>
<div class="tabs-content">
  <div class="print-option">
    <h4>Share these tips with your home. <a href="#">Print now</a></h4>

  </div>
  <div class="content active" id="panel1">
    <div class="saved-tip">
      <img class="saved-tip-icon" src="http://placehold.it/20x20">
      <h5>Tip title</h5>

      <div class="saved-tip-options">	<a class="saved-tip-done" href="#"><i class="fa fa-check"></i></a>
        <a class="removed-saved-tip" href="#"><i class="fa fa-times"></i></a>

      </div>
    </div>
    <div class="saved-tip">
      <img class="saved-tip-icon" src="http://placehold.it/20x20">
      <h5>Tip title</h5>

      <div class="saved-tip-options">	<a class="saved-tip-done" href="#"><i class="fa fa-check"></i></a>
        <a class="removed-saved-tip" href="#"><i class="fa fa-times"></i></a>

      </div>
    </div>
  </div>
  <!-- eo / panel1 -->
  <div class="content" id="panel2">
    <div class="saved-tip">
      <img class="saved-tip-icon" src="http://placehold.it/20x20">
      <h5>Tip title</h5>

      <div class="saved-tip-options">	<a class="saved-tip-done" href="#"><i class="fa fa-check"></i></a>
        <a class="removed-saved-tip" href="#"><i class="fa fa-times"></i></a>

      </div>
    </div>
    <div class="saved-tip">
      <img class="saved-tip-icon" src="http://placehold.it/20x20">
      <h5>Tip title</h5>

      <div class="saved-tip-options">	<a class="saved-tip-done" href="#"><i class="fa fa-check"></i></a>
        <a class="removed-saved-tip" href="#"><i class="fa fa-times"></i></a>

      </div>
    </div>
    <div class="saved-tip">
      <img class="saved-tip-icon" src="http://placehold.it/20x20">
      <h5>Tip title</h5>

      <div class="saved-tip-options">	<a class="saved-tip-done" href="#"><i class="fa fa-check"></i></a>
        <a class="removed-saved-tip" href="#"><i class="fa fa-times"></i></a>

      </div>
    </div>
  </div>
  <!-- eo / panel2 -->
</div>
<!-- eo // tabs content -->
</div>

Upvotes: 1

LTasty
LTasty

Reputation: 2008

You need put the each into click function because now with your code each call only when document is ready.

$('.saved-tip-done').click(function (e) {

    $(this).toggleClass('marked-done');
    e.preventDefault();
    $(this).closest('.saved-tip').clone().appendTo('#panel2');
    $(".tab-title:first a").text("Saved (" + $('#panel1 .saved-tip').length+")");
    $(".tab-title:last a").text("Saved (" + $('#panel2 .saved-tip').length+")");
});

You can remove each and get the number of save tip in one line using $('#panel1 .saved-tip').length

http://jsfiddle.net/jvdnbw4q/1/

Upvotes: 1

Related Questions