0

I've got a mail box menu which you can right-click and choose to delete a folder which looks a bit like the following:

<ul>
    <li>
        Level 1
        <span class="badge badge-success MailCount">60</span>
        <ul>
            <li>
                Level 2 a
                <span class="badge badge-success MailCount">10</span>
                <ul>
                    <li>
                        Level 2 a i
                        <span class="badge badge-success MailCount">10</span>
                    </li>
                    <li>
                        Level 2 b ii
                        <span class="badge badge-success MailCount">10</span>
                    </li>
                    <li>
                        Level 2 c iii
                        <span class="badge badge-success MailCount">10</span>
                    </li>
                </ul>
            </li>
            <li>
                Level 2 b
                <span class="badge badge-success MailCount">10</span>
            </li>
            <li>
                Level 2 c
                <span class="badge badge-success MailCount">10</span>
            </li>
        </ul>
    </li>
</ul>

And my Javascript file looks like the following;

$(document).ready(function() {
    "use strict";

    $(document).on('click', function(e) {

        var action = $(e.target).data('action'),
            anchor = '',
            clicked = $('.clicked'); // This is applied when you right-click teh item

        switch (action) {
            // Rename a mail sub-folder...
            case 'rename-folder':

                break;
        }

    });
});

So at this point in time, all I simply do is clicked.remove(); however now I'd like to take the .clicked > .MailCount value and take it away from all .MailCount above and if .clicked has direct ul which are going to also be deleted, their values should be added up with the current and removed from the above value.

I hope I haven't made that sound more complicated than what it is. Basically if you remove Level 2 a, it'll add up Level 2 a + Level 2 a i + Level 2 a ii + Level 2 a iii and take them away from Level 1

Tyler
  • 854
  • 1
  • 10
  • 26
  • Why are you attaching the handler to `document` instead of something like `$(".rename-folder").click(...)`? – Barmar Nov 18 '16 at 23:25
  • If it's because the elements get added dynamically, you should use event delegation, see http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – Barmar Nov 18 '16 at 23:25
  • Why isn't `Level 2 a i + Level 2 a ii + Level 2 a III` included in `Level 2 a`? – Barmar Nov 18 '16 at 23:29
  • What happens if they delete `Level 2 a ii`? It looks like we should subtract its mail count from `Level 1`, but not from `Level 2 a`. How does it know which parents to subtract from? Is the total only in `Level 1`? – Barmar Nov 18 '16 at 23:33
  • @Barmar I do it like this as it is better for how the rest of my file has been scripted. The folder count is on all leading up to the deleted item if available (this is only an unread message count). So deleting `Level 2 b ii` would subtract `Level 2 b ii`'s value from `Level 2 a` and `Level 1` – Tyler Nov 18 '16 at 23:38
  • But it doesn't look like `Level 2 a ii` is included in `Level 2 a`. Shouldn't `Level 2 a` be at least 30? – Barmar Nov 18 '16 at 23:39

2 Answers2

1

Use .map() to loop over all the .MailCount elements in the li being removed and add up all their contents. Then subtract it from the total in the top-most .MailCount.

var remove_total = 0;
clicked.find(".MailCount").map(function() {
    remove_total += parseInt($(this).text(), 10);
});
clicked.parents("li").last().find(".MailCount").first().text(function(i, oldText) {
    return parseInt(oldText, 10) - remove_total;
});
clicked.remove();
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • See [here](http://admin.rafflebananza.com/Account/Messages_New.html#) for a live demo. Going over the entire script as it needs to be done so didn't want to post this really and regarding how I've mapped my list above, I mocked this up before and a bit under the weather - It is meant to be 30! – Tyler Nov 18 '16 at 23:46
  • Thank you for this help, I'll go over it once I get some food inside of me so I can focus more! I've rated your answer up and will hopefuly accept it as an answer soon. – Tyler Nov 18 '16 at 23:48
  • 1
    If each level includes all the children counts, then we should just subtract the current level from the total, not the current level and the children, because then we're subtracting the children twice. – Barmar Nov 18 '16 at 23:52
  • Wow, I'm going for a break, what a complete and utter stupidity moment! Just subtract `clicked.find('.MailCount')` from `clicked.parent().find('.MailCount')` as the closest `.MailCount` would already show the count for all the children! – Tyler Nov 18 '16 at 23:59
  • You actually need to subtract it from the first `.MailCount` in each `.parents("li")` – Barmar Nov 19 '16 at 00:03
  • I'm getting an error from your snippet `Uncaught ReferenceError: oldTesxt is not defined(...)` – Tyler Nov 19 '16 at 03:08
  • Hiya @Barmar, I've been trying to go through your code to resolve this problem as this method is going to be used in multiple places however I've not been successful and could do with your help please. – Tyler Nov 20 '16 at 02:21
  • You have a typo. `oldTesxt` should be `oldText`. – Barmar Nov 20 '16 at 16:19
  • My above comment was a typo, I was meant to say `Uncaught ReferenceError: oldText is not defined(...)` Please see my answer, I've got this working :) – Tyler Nov 20 '16 at 17:54
  • Barmar, wouldn't it be simpler to just take a new total count? If we know the list is complete, then that seems simpler. If it's not, then obviously that wouldn't work. – random_user_name Nov 20 '16 at 17:58
  • I had a typo in the answer, `oldtext` versus `oldText`. I was also missing one of the arguments. – Barmar Nov 20 '16 at 18:02
  • Regenerating all the counts from scratch is certainly another way to do it. – Barmar Nov 20 '16 at 18:03
  • Yours now gets the top level count and alters it but not any parents along the way. Also if you want to get this working, please add comments as I don't understand this method and it would be very useful to be able to do so. Thanks – Tyler Nov 20 '16 at 21:22
  • My answer is based on the HTML in the question, where only the top-level count includes the children. You should edit the question to show what it's really like. – Barmar Nov 20 '16 at 21:51
  • Each level shows the total unread mails so if a folder has sub-folders, then that folder shows the total for the sub-folders within. Let's just say add some commenting so I can understand what you've done such as the `+=`? – Tyler Nov 21 '16 at 00:37
  • Level 2 a doesn't have the total for Level 2 a i/ii/iii in it. Fix the question to match reality. – Barmar Nov 21 '16 at 01:07
0

Got this eventually working using the following:

case 'delete-folder':
    var thisUnread = clicked.find('.MailCount:first').text();
    clicked.parents('li').each(function() {
        var parentUnread = $(this).find('.MailCount:first').text();
        if ((parentUnread - thisUnread) > 0 ) {
            $(this).find('.MailCount:first').text((parentUnread - thisUnread));
        } else {
            $(this).find('.MailCount:first').remove();
        }
        clicked.remove();
    });
    break;
Tyler
  • 854
  • 1
  • 10
  • 26