Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent multiple occurrences of event handlers #218

Closed
arvgta opened this issue Aug 9, 2021 · 2 comments
Closed

Prevent multiple occurrences of event handlers #218

arvgta opened this issue Aug 9, 2021 · 2 comments
Labels

Comments

@arvgta
Copy link
Owner

arvgta commented Aug 9, 2021

EDIT: Not necessary to adopt this approach because there were no timing problems after all...


**Old code:**
let iFn = function (a, b, c = false) { 
    if ((this === document || this === window) && a=="DOMContentLoaded") setTimeout(b); else this.ael(a,b,c);
};  // if "DOMContentLoaded" - execute function, else - add event listener

EventTarget.prototype.ael = EventTarget.prototype.addEventListener; // store original method
EventTarget.prototype.addEventListener = iFn; // start intercepting event listener addition

...works fine but can cause timing issues because of the setTimeout(b) bit, that executes the handler on the fly, instead of waiting for the DOMContentLoaded event itself.


Therefore, I have attempted to replace the setTimeout(b) bit with a snippet, that attempts to inject:

  • once: true

into all calls of addEventListener with type DOMContentLoaded.

In this new scenario, the DOMContentLoaded event is fired programmatically by Ajaxify itself beforehand.

New code: (in this file, which is active in the testcase below)

let iFn = function (a, b, c = false) { 
	if ((this === document || this === window) && a=="DOMContentLoaded") {
		if(typeof c == "boolean") c = { capture: c, once: true };
		else c.once = true;
	}
	this.ael(a,b,c);
};
EventTarget.prototype.ael = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = iFn;

...which works fine, but for some reason, the pass right after initial load does not work - as can be seen here at the moment:

and

  • 4nf.org - albeit without logging messages (if you see any funnies, please shout!)

(The DOMContentLoaded event is fired successfully, but the handler is not called in that case only)


How to reproduce the bug in more detail:

  1. Enter www.oeko-fakt.de
  2. Open the Chrome console
  3. You should see the message: "DCL triggered" followed by "Ajaxify loaded..." (as expected on initial load - no problem)
  4. Navigate to another page - "DCL triggered" is not shown in the console (not as expected)
  5. Navigate to further pages - "DCL triggered" is shown in the console (as expected)

So the bug is on step 4) above

Please note also:

  • I have verified, that the programmatical firing of DOMContentLoaded works as expected - also on step 4) above
  • The message "DCL triggered" indicates, when the respective handler function was executed, not the firing of the event

(Link for my own purposes: ) Erase any salient handlers

arvgta added a commit that referenced this issue Aug 10, 2021
@arvgta arvgta changed the title Prevent multiple firing of event handlers Prevent multiple occurences of event handlers Aug 15, 2021
@arvgta arvgta changed the title Prevent multiple occurences of event handlers Prevent multiple occurrences of event handlers Aug 15, 2021
@arvgta
Copy link
Owner Author

arvgta commented Aug 19, 2021

The bug was identified: the firing of the event was happening before the registration of the handler had finished.
Solved by adding a setTimeout() with minimal delay (0 milliseconds) to the firing of the event.

Now seems to work!

@arvgta arvgta closed this as completed Aug 19, 2021
@arvgta
Copy link
Owner Author

arvgta commented Aug 23, 2021

Just for the sake of completeness - this approach has been discarded in the course of some testing...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant