javascriptjquerysammy.js

Document level event listeners being duplicated


I am using SammyJS to route a website, and I'm also using this file structure, Inside of my controller/, I have 4 main pages. Inside, they look like this,

(function() {
  var app = Sammy.apps.body;
  
  app.get('#/clients', function(context) {
    context.render('/view/clients/index.html', function(view) {
      $('body').html(view);
    });
  });
  
  app.get('#/clients/edit', function(context) {
    context.render('/view/clients/edit.html', function(view) {
      $('body').html(view);
      
      $(document).on('click', '#updateClient', function() {
        //Do stuff for updating client here...
      });
    });
  });
});

With the first navigation everything works fine. The HTML and JavaScript load perfectly and the buttons work as intended. But upon page navigation (I'm using href's to handle the navigation) to another page and then back, the event listeners are being duplicated, as can be seen here (using Chrome)

Before(first navigation)

After(second navigation)

Is there any way to stop this? I understand using $('#idNameHere').on('click', function() {...}); works, but not on dynamically generated elements. Also, page refresh works to delete the listeners (sort of obvious). I am led to believe that could also be part of SammyJS's way of running, where it keeps JavaScript files running in the background even after you navigate away from the page.


Solution

  • You can just move the event listener out to the root, so that it's set only once. Since the event listener is set on the document, it'll work fine with dynamically added content.

    (function() {
      var app = Sammy.apps.body;
    
      $(document).on('click', '#updateClient', function() {
        //Do stuff for updating client here...
      });
    
      app.get('#/clients', function(context) {
        context.render('/view/clients/index.html', function(view) {
          $('body').html(view);
        });
      });
    
      app.get('#/clients/edit', function(context) {
        context.render('/view/clients/edit.html', function(view) {
          $('body').html(view);
      });
    });