Opened 8 years ago

Last modified 5 years ago

#17588 new defect

dojo/on sometimes interferes with other sites' scripts when using embedded dojo

Reported by: Matt Senter Owned by:
Priority: undecided Milestone: 1.15
Component: Events Version: 1.9.1
Keywords: Cc:
Blocked By: Blocking:


Bear with me because this is a very specific use case with a very specific bug (and a fix!) Ok, so, I had a need to embed a custom-built dojo (for example for injecting via Chrome extension.) One of the most important things to consider when doing something like this is to make sure your script does not interfere with any existing scripts, right? Well, I had to customize the build system a bit to make this possible, but even after doing so, some sites still kept getting interference (i.e. "breaking") when my script was injected. I narrowed it down to the use of dojo/on when adding events to the global window object.

If you take a look at on.js at line 47 (v1.9.1,) there is a check to see if the target object has its own on() function, and if so, call it (with a few exceptions for jQuery and Prototype, etc.) The problem was whenever you do something like this:

on(window, "resize", ...)

...the target references the global window, and some sites were creating their own on() method on the global window object! So, what was happening was that I was throwing resize events into some strange existing global on() function, which would throw the site's existing script into chaos. Long story short, my attempt to add an event listener was getting short-circuited by the pre-existing script.

The fix: replace the block at line 47 of on.js with something like this:

if(typeof target.on == "function" && typeof type != "function" && !target.nodeType
	&& target != window && target != top && target != parent && target != document){
	// delegate to the target's on() method, so it can handle it's own listening if it wants (unless it
	// is DOM node and we may be dealing with jQuery or Prototype's incompatible addition to the
	// Element prototype
	return target.on(type, listener);

Perhaps there is another method in dojo that helps us determine if an object is a default global javascript object, but I couldn't find it. Ultimately, the goal is to check target to make sure it is not a default javascript object that normally does not come with its own on() function. This will allow us to proceed to the on.parse() call where ultimately something like addEventListener will be called.

Change History (4)

comment:1 Changed 8 years ago by Matt Senter

Oh, I forgot to mention a place you could test this: Google Calendar. They create a global window.on() function there.

comment:2 Changed 8 years ago by bill

Last edited 8 years ago by bill (previous) (diff)

comment:3 Changed 6 years ago by dylan

Milestone: tbd1.12

comment:4 Changed 5 years ago by dylan

Milestone: 1.131.15

Ticket planning... move current 1.13 tickets out to 1.15 to make it easier to move tickets into the 1.13 milestone.

Note: See TracTickets for help on using tickets.