2

The problem

I have an (AWS serverless) chat application which has a send button. When clicked, it POSTS a message to a DynamoDB table. I've debugged the backend of things, and it seems like the bug is coming from my javascript. I've posted relevant code below.

My chat.html file containing the send button:

...
<input type="text" class="form-control" id="message"/>
<span class="input-group-btn">
  <button type="button" class="btn btn-primary" id="send">Send</button>
</span>
...
<script src="static/script.js"></script>
<script type="text/javascript">
  $(function() {
     $("#send").off().on('click', window.Chat.send);
  });
</script>

My 'script.js' file containing the Chat.send():

Chat.send = function(){
  $.post(endpoint + location.hash.substring(1), {message: $('#message').val()}).done(function(){
    $('#message').val('').focus();
    Chat.load();
  })
};

Chat.load = function(){
  // periodically makes a GET request to load new messages dynamically
  // a little lengthy and not sure relevant but will edit this with the code if someone needs it
}

Edit after following @@MauricioCárdenas's comment

My chat.html file's script was revised to:

<script type="text/javascript">
  $(function() {
     document.removeEventListener('click', window.Chat.send);
     $("#send").off().on('click', window.Chat.send);
  });
</script>

Issue still persists.

Edit after following @Teemu's comment When I right click on #send button and inspect then head to "Event Listeners" tab, under click I get the following:

click
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >document [Remove] bootstrap.min.js:6
  >button#send.btn.btn-primary [Remove] script.js:78

Perhaps bootstrap is attaching multiple click events to my button? What's confusing is that, why is it only sending my message twice and not 10 times, given the number of attached event listener above? I tried removing the 9 event listeners from bootstrap but still no dice.

What I have tried thus far

Per similar SO posts from the past, I have tried using e.stopImmediatePropagation() (post):

$('#send').off().on('click', function(e){
  e.stopImmediatePropagation();
  window.Chat.send();
})

I've tried returning false (post):

$('#send').off().on('click', function(){
  window.Chat.send();
  return false;
})

I've tried debugging the click event using $._data($('#send')[0], "events") in the console and viewing the handler function - of which there's only one(post):

// this returns an array with one element and points to the correct handler function 
{click: Array(1)}
...
...
// the handler function is below
Chat.send = function() {
  //...see above for the definition
}
pairwiseseq
  • 313
  • 2
  • 13
  • Have you double checked rendered HTML doesn't contain duplicate id "send"? – Will Jan 06 '20 at 17:11
  • I'd assume `$._data` can find the attached jQuery events only. Open "Inspector" tab in the DevTools and search the button from the code, there you can see all the attached events to the button. – Teemu Jan 06 '20 at 17:12
  • @WillCain, I just double checked. No duplicate tags with `#send`. @Teemu, wow, okay this is actually giving me an interesting lead. Please see my edited post. – pairwiseseq Jan 06 '20 at 17:22
  • I'm not familiar with Bootstrap, but when you have a real button, I suppose you actually don't need `btn` and `btn-primary` classes. You could test what happens without attaching those classes to the button. – Teemu Jan 06 '20 at 17:28
  • @Teemu, yes, that was also my suspicion. I removed the button's class, but I still get two `click` events. – pairwiseseq Jan 06 '20 at 17:30
  • 1
    Well, unfortunately it seems we're at a situation as described [in this meta post](https://meta.stackoverflow.com/q/392470/1169519). You've similarly a large code, which can't be narrowed down to reproduce the problem, and we can give some debug advices only ... – Teemu Jan 06 '20 at 17:36
  • Your `send` method looks to have a typo as well. You are referencing `location.has.substring(1)` which I'm guessing is supposed to be `location.hash.substring(1)` – jmfolds Jan 06 '20 at 17:39
  • 1
    Thanks for the meta post. I'll dig more deeper and provide my answer! @jmfolds, thanks for tracking that typo! – pairwiseseq Jan 06 '20 at 17:42
  • 1
    Instead of trying stopImmediatePropagation(), try using preventDefault(). That will cancel any other event triggered by the same action. – Mauricio Cárdenas Jan 06 '20 at 17:47
  • try other events, mousedown, mouseup? – Rainb Jan 06 '20 at 17:53
  • @MauricioCárdenas, just tried `e.preventDefault()` but same issue. @Rainb, tried both events but same issue. – pairwiseseq Jan 06 '20 at 17:59
  • @pairwiseseq Is it possible that you're loading the js multiple times? – Mauricio Cárdenas Jan 06 '20 at 18:00
  • @MauricioCárdenas, so I did look into this as well. If you mean if I'm loading the js multiple times in my `chat.html` file, then, no, I'm only loading it once. However, I have multiple redirects to other html files that also load the same js. But can a button's click event from a different html remain listening even after a redirect to a different html? – pairwiseseq Jan 06 '20 at 18:02
  • 1
    It does sometimes, it depends on how you do it. You can debug this using a self-executing function when you load the script and verify if it's in fact being loaded just once. Now, if you're certain it is not loading the js file multiple times, try using removeEventListener() and try to remove everything attached to that event before adding the handler to your button. – Mauricio Cárdenas Jan 06 '20 at 18:36
  • @MauricioCárdenas, first, please excuse my lack of knowledge with js. My script is already wrapped inside self-executing function `(function scopeWrapper($){ ..my code..}(jQuery));`. I put inside a simple `console.log('hi')` and indeed, `hi` is outputted only once. Regarding, `removeEventListener()`, please see my edit above to see if my implementation is correct. – pairwiseseq Jan 06 '20 at 19:08
  • @pairwiseseq Worry not, we all learn everyday :) Yeah, I saw your function, but sometimes jquery does funky stuff, and yes, your implementation is correct. Try this: `$(function() { $("#send").off('click').on('click', window.Chat.send); });` – Mauricio Cárdenas Jan 06 '20 at 19:20
  • @MauricioCárdenas - just tried `$(function() { $("#send").off('click').on('click', function() { window.Chat.send }); });` - still no dice. – pairwiseseq Jan 06 '20 at 19:23
  • 1
    @pairwiseseq This isn't tested, and I'm not certain it'll work, but let's see if this works: `$(function() { document.removeEventListener('click', window.Chat.send); $("#send").off().on('click', function(e) { e.preventDefault(); e.stopImmediatePropagation(); window.Chat.send(); }); });` – Mauricio Cárdenas Jan 06 '20 at 19:25
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205463/discussion-between-mauricio-cardenas-and-pairwiseseq). – Mauricio Cárdenas Jan 06 '20 at 19:27
  • @MauricioCárdenas - I just threw the kitchen sink per your recommendation, but `click` is still triggering twice. – pairwiseseq Jan 06 '20 at 19:28
  • 1
    @pairwiseseq There you see, Chipster was right in their answer in the meta post. After two hours you haven't got your problem solved, and all are just getting frustrated, and that's no more fun. – Teemu Jan 06 '20 at 19:53
  • The only thing you can do, is to start from the scratch with new files. Include the minimal code to replicate the problematic process from the old files, and if you need some server-side code, create new code, response with dummy data wihout interfering the database or datafiles, or if possible, rather emulate the data on the client-side. Then, if the problem doesn't occur, add small parts of the old code until the issue gets fired. Then you've most likely found the root cause. If you still can't fix the code, then ask a question and include the reproducible example you've just created. – Teemu Jan 06 '20 at 20:11

0 Answers0