James Carlyle-Clarke James Carlyle-Clarke - 1 month ago 12
jQuery Question

jQuery Off() not working in Chrome Extension

I've created a Chrome Extension based on https://robots.thoughtbot.com/how-to-make-a-chrome-extension (look at the end for the completed files)

I've made two changes. I used JQuery 3.1.1 minimized instead of the older one given in the page above; and I changed content.js:

chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
$(document).off("touchmove mousewheel mousemove scroll");
}
}
);


The $(document).off() command is not working when I click the extension's button with an appropriate test page opened. It doesn't give an error, it just doesn't do anything.

I've checked. If I type
$(document).off("touchmove mousewheel mousemove scroll");
into the console on the page I want to affect, it works fine. If run in the extension it isn't.

I tried checking that
document
was correct in the extension, and
document.domain
gives the correct result when checked in a breakpoint in the extension (and in the console on the page).

I tried checking
jQuery._data( jQuery(document)[0]).events["touchmove"]
(and "mousewheel", "mousemove", "scroll") and it works in the console, but I get an error (
Cannot read property 'touchmove' of undefined
) if I breakpoint the extension. When I checked further,
jQuery._data( jQuery(document)[0])
gives the following:

In console:

Object
events: Object
handle: function (e)
__proto__: Object


In breakpoint:

Object
__proto__: Object


I've tried a few other things (for example, that jQuery is accessible and working, and so on).

Can anyone help?

Answer

Your content script is in a different context/scope from that of page scripts (scripts that already exist in the webpage). In order to execute code in the page script context, you have create and insert a <script> element to the page's DOM.

You could change your code to:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if( request.message === "clicked_browser_action" ) {
            let newScript = document.createElement('script');
            newScript.innerHTML='$(document).off("touchmove mousewheel mousemove scroll");';
            document.head.appendChild(newScript);
        }
    }
);

The added script gets run because it is now a <script> element in the DOM. The browser recognizes that a <script> element was added and evaluates it (executes the code contained) as soon as the script which inserted it is no longer processing. It does basically the same thing for any other element you add to the DOM. Because it is part of the page, the code inside the <script> gets run in the page script context/scope.