How to access jQuery in HTML 5 web worker

I am unable to to access jQuery inside an HTML5 web worker. Is there a way I can do that?

Upvotes: 24

Views: 27370

Answers (7)

Tegman
Tegman

Reputation: 11

jQuery 3.3.1

I used Luke Vo's code and had to add some extra. I placed this function in my webworker and works great:

    const webWorkerJQueryFix = () => {
    document = self.document = { parentNode: null, nodeType: 9, toString: () => { return "FakeDocument" } };
    window = self.window = self;
    const fakeElement = Object.create(document);
    fakeElement.nodeType = 1;
    fakeElement.toString = () => { return "FakeElement" };
    fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
    fakeElement.ownerDocument = document;

    document.innerHTML = "";
    document.head =
        document.body =
        fakeElement;
    document.ownerDocument =
        document.documentElement =
        document;

    document.createElement =
        document.getElementById =
        document.getElementsByClassName =
        document.getElementsByTagName = () => { return [fakeElement]; };

    document.appendChild = (child) => { return child; };

    document.createDocumentFragment = () => {
        this.appendChild = document.appendChild;
        return this;
    };

    document.getAttribute =
        document.removeChild =
        document.addEventListener =
        document.removeEventListener =
        document.setAttribute = () => { return null; };

    document.cloneNode = () => {
        this.cloneNode = document.cloneNode;
        this.lastChild = {
            checked: false,
        }
        return this;
    };

    document.childNodes = [];
    document.implementation = {
        createHTMLDocument: () => { return document; }
    }
}

Upvotes: 1

Luke Vo
Luke Vo

Reputation: 20658

The answer of Tomáš Zato was correct, but no longer works with newer jQuery version. I added some more for jQuery 3.1.1:

var document = self.document = { parentNode: null, nodeType: 9, toString: function () { return "FakeDocument" } };
var window = self.window = self;
var fakeElement = Object.create(document);
fakeElement.nodeType = 1;
fakeElement.toString = function () { return "FakeElement" };
fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
fakeElement.ownerDocument = document;

document.head = document.body = fakeElement;
document.ownerDocument = document.documentElement = document;
document.getElementById = document.createElement = function () { return fakeElement; };
document.createDocumentFragment = function () { return this; };
document.getElementsByTagName = document.getElementsByClassName = function () { return [fakeElement]; };
document.getAttribute = document.setAttribute = document.removeChild =
    document.addEventListener = document.removeEventListener =
    function () { return null; };
document.cloneNode = document.appendChild = function () { return this; };
document.appendChild = function (child) { return child; };
document.childNodes = [];
document.implementation = {
    createHTMLDocument: function () { return document; }
}

Upvotes: 15

tim peterson
tim peterson

Reputation: 24305

There is a nice plugin to use Web Worker with jQuery by one of jQuery's own leaders. Check out his plugin on GitHub.

Upvotes: 0

Delgan
Delgan

Reputation: 19617

As an alternative, you can use Cheerio.

Fast, flexible & lean implementation of core jQuery designed specifically for the server.

You will simply need to browserify the module, and loading the resulting file into your web worker. Then, you will be able to parse your string document and query it like jQuery does:

$ = cheerio.load('<h2 class="title">Hello world</h2>')

Upvotes: 0

Anirudh Prabhu
Anirudh Prabhu

Reputation: 53

Has anyone tried the jQuery - No DOM Edition? https://github.com/kpozin/jquery-nodom.

This is a small subset of the jQuery library intended for use in Web Worker contexts, where most of the browser API does not exist.

This is achieved primarily by modifying jQuery build instructions (Makefile) to only include the non-DOM modules.

This might help resolve the issue as this build has no DOM dependency, which is a hurdle when importing jQuery in webworker. Will try to provide some sample code soon for this

Upvotes: 4

Tom&#225;š Zato
Tom&#225;š Zato

Reputation: 53129

tl;dr: include this script before jQuery

JQuery initally accesses lots of document properties to check for browser features. document is not defined in Worker and you actually cannot create Document instance in web workers at this moment. JQuery isn't prepared for that - as you could see in comments on your question, nobody seems to understand what would you do with JQuery without DOM.

Since, as I said, JQuery needs document to initialise, I created a dummy fake document object. This object acts as real document during JQuery tests:

var document = self.document = {parentNode: null, nodeType: 9, toString: function() {return "FakeDocument"}};
var window = self.window = self;
var fakeElement = Object.create(document);
fakeElement.nodeType = 1;
fakeElement.toString=function() {return "FakeElement"};
fakeElement.parentNode = fakeElement.firstChild = fakeElement.lastChild = fakeElement;
fakeElement.ownerDocument = document;

document.head = document.body = fakeElement;
document.ownerDocument = document.documentElement = document;
document.getElementById = document.createElement = function() {return fakeElement;};
document.createDocumentFragment = function() {return this;};
document.getElementsByTagName = document.getElementsByClassName = function() {return [fakeElement];};
document.getAttribute = document.setAttribute = document.removeChild = 
  document.addEventListener = document.removeEventListener = 
  function() {return null;};
document.cloneNode = document.appendChild = function() {return this;};
document.appendChild = function(child) {return child;};

Beware that this fake document is only meant to allow jQuery to load, it won't allow any real DOM operations.

Example usage:

importScripts("workerFakeDOM.js");
importScripts('jquery-2.1.4.min.js');
console.log("JQuery version:", $.fn.jquery);

Test script

Allows you to try various versions of JQuery with my script.

JSfiddle

Check that you're using http://, my domain doesn't work with https://.

Download as script

Upvotes: 27

meawoppl
meawoppl

Reputation: 2802

Does using:

importScripts("jQueryWhatever.js");
$.blahblahblah();

Not work as expected? I suspect it will load jQuery without trouble, but most of the calls associated with good-ole $ will not work as expected as there is no DOM access inside a WebWorker.

Upvotes: 0

Related Questions