0

I am trying to create a dropdown menu that I dynamically insert into using jQuery. The objects I'm inserting are notifications, so I want to be able to mark them as read when I click them.

I have an AJAX call that refreshes the notifications every second from the Django backend.

Once it's been refreshed, I insert the notifications into the menu.

I keep an array of the notifications so that I don't create duplicate elements. I insert the elements by using .append(), then I use the .on() method to add a click event to the <li> element.

Once the click event is initiated, I call a function to .remove() the element and make an AJAX call to Django to mark the notification as read.

Now my problem:

The first AJAX call to mark a notification as read always works. But any call after that does not until I refresh the page. I keep a slug value to identify the different notifications.

Every call I make before the refresh uses the first slug value. I can't figure out why the slug value is tied to the first element I mark as read.

Also, if anyone has a better idea on how to approach this, please share.

Here's my code:

var seen = [];

function removeNotification(elem, urlDelete) {
    elem.remove();
    console.log("element removed");

    $.ajax({
        url: urlDelete,
        type: 'get', 
        success: function(data) {
            console.log("marked as read");
        },
        failure: function(data) { 
            console.log('failure to mark as read');
        }
    }); 
}

function insertNotifications(data) {
    for (var i = 0; i < data.unread_list.length; i++) {
        var slug = data.unread_list[i].slug
        var urlDelete = data.unread_list[i].url_delete;
        if (seen.indexOf(slug) === -1) {

            var elem = $('#live-notify-list').append("<li id='notification" +
                i + "' > " + data.unread_list[i].description + " </li>");

            var parent = $('#notification' + i).wrap("<a href='#'></a>").parent();

            seen.push(slug);

            $( document ).ready(function() {
                    $( document ).on("click", "#notification" + i, function() {
                    console.log("onclick " + slug);
                    removeNotification(parent[0], urlDelete);
                });
            });
        }
    }
}

function refreshNotifications() {
    $.ajax({
        url: "{% url 'notifications:live_unread_notification_list' %}",
        type: 'get',
        success: function(data) {
            console.log("success");
            insertNotifications(data);
        },
        failure: function(data) { 
            console.log('failure');
        }
    }); 
}
setInterval(refreshNotifications, 1000);
ctzdev
  • 646
  • 2
  • 9
  • 24
  • Looks like an ["infamous loop"](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) issue, the `slug variable is inside an event handler etc. and what the heck is that `document.ready` thing doing in the middle of the code, remove it. – adeneo Dec 05 '15 at 23:32
  • Where did you find the urlDelete? – Shyghar Jun 28 '16 at 15:38

1 Answers1

1

I really don't know what do you mean with parent[0] in

removeNotification(parent[0], urlDelete);

I think you can simply try $(this)

removeNotification($(this), urlDelete);

but to be honest I find to put

$( document ).ready(function() {
   $( document ).on("click", "#notification" + i, function() {
      console.log("onclick " + slug);
      removeNotification(parent[0], urlDelete);
   });
});

inside a loop .. its bad thing try to put it outside a function and use it like

$( document ).ready(function() {
       setInterval(refreshNotifications, 1000);
       $( document ).on("click", "[id^='notification']", function() {
          console.log("onclick " + slug);
          removeNotification($(this), urlDelete);
       });
 });

and try to find a way to pass a urlDelete which I think it will be just one url

Mohamed-Yousef
  • 23,946
  • 3
  • 19
  • 28
  • Changed it, but still the AJAX request only goes to the first notification I try to mark. For example, say I have `[110, 120, 130]` and I mark `120` as read. Every time I try to click a notification, the url request always goes to `120`. – ctzdev Dec 05 '15 at 23:33
  • Amazing, it works perfectly. I'm fairly new to jQuery, I picked it up recently for a school project. Do you mind explaining why your changes work so that I may learn from this and not commit the same mistake again? – ctzdev Dec 06 '15 at 08:54
  • 1
    @ChrisTarazi When you put your code inside loop it will print the same code each time for each li.notification (it mean click event for li 1 and click event for li 2 ... etc) by [selectors](http://code.tutsplus.com/tutorials/the-30-css-selectors-you-must-memorize--net-16048) you can select all the ids starts with word notification by using ^= like I did in example .. so I recommend to read about selectors .. and use $(this) to refer to the same element you clicking on .. simple?? – Mohamed-Yousef Dec 06 '15 at 15:11
  • 1
    @ChrisTarazi If you need to learn jquery https://www.youtube.com/watch?v=GNb8T5NBdQg&list=PL6B08BAA57B5C7810 this is a very simple and helpful tutorials .. this how I start jquery .. Good Luck to you :) – Mohamed-Yousef Dec 06 '15 at 15:18