user63898
user63898

Reputation: 30895

Chrome extention using jquery in content script resolve error when creating dialog window

I try to use jQuery and jQuery-UI in my Chrome extension. I try to create in the content script dialog window each time new tab is created but I keep getting:

Property '$' of object [object Window] is not a function 

I guess I'm doing something wrong loading the scripts. Here's what I have:

{
"name":"Sample",
"description":"This is a sample",
"manifest_version":2,
"version":"2",
"background":{
    "scripts":["background.js"]
},
"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["jquery-1.8.3.min.js","jquery-ui.js","client.js","myscript.js"]
      "run_at":"document_end",
      "all_frames": true
    }
  ],
"web_accessible_resources": [
    "client.js","jquery-1.8.3.min.js","jquery-ui.js"
  ],
"permissions": [ 
        "unlimitedStorage",
        "http://*/",
        "<all_urls>",
        "tabs"
   ]
}


myscript.js ( the content script ):

var ss = document.createElement('script');
ss.type = "text/javascript";
ss.src = chrome.extension.getURL('jquery-1.8.3.min.js');
ss.onload = function() {
    ss.parentNode.removeChild(ss);
     console.log("jquery-1.8.3.min.js loaded");

};

var ss_ui = document.createElement('script');
ss_ui.type = "text/javascript";
ss_ui.src = chrome.extension.getURL('jquery-ui.js');
ss_ui.onload = function() {
    ss_ui.parentNode.removeChild(ss_ui);
    console.log("jquery-ui.js loaded");
};


var s = document.createElement('script');
s.type = "text/javascript";
s.src = chrome.extension.getURL('client.js');
s.onload = function() {
    s.parentNode.removeChild(s);
    console.log("client.js loaded");
};

        try{

            (document.head||document.documentElement).appendChild(ss);
            (document.head||document.documentElement).appendChild(ss_ui);
            (document.head||document.documentElement).appendChild(s);

        }catch(e){
          console.log("exception in appendChild");
        }  



client.js ( where I create the dialog )

       try{
        console.log("Starting to create tabel");

        var layerNode= document.createElement('div');
            layerNode.setAttribute('id','dialog');
            layerNode.setAttribute('title','Basic dialog');
        var pNode= document.createElement('p');
            pNode.innerHTML = "This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.";

        layerNode.appendChild(pNode);
        document.body.appendChild(layerNode);


        jq162 = jQuery.noConflict(true);
(function($){
    $(document).ready(function() {
       $("#dialog" ).dialog();
    });
})(jq162);

        }
        catch(e){
          console.log("script in page exception in appendChild"+e);
          //alert(e);
        }  

when I see in the console to see the order of prints im getting :

Starting to create tabel client.js:2
script in page exception in appendChildTypeError: Cannot call method 'dialog' of null client.js:26
client.js loaded chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/myscript.js:24
jquery-1.8.3.min.js loaded chrome-extension://mmoccjinakdjcmhjdjghhjnihbfkkgkp/myscript.js:6
jquery-ui.js loaded   

What am I doing wrong here?

Upvotes: 1

Views: 2603

Answers (2)

PAEz
PAEz

Reputation: 8542

Usual disclaimer, I don't really do jQuery... but I saw an obvious problem with your code and so gave it a shot...

Get rid of client.js, its no longer needed after you added the files it injects to the content script part of the manifest. After you added them to the manifest Chrome will now inject them for you. Once you do this it starts to half work.

After that I noticed that the dialog came up but had no graphics / styling so you need to add the css file to the content script part of the manifest to get injected. Now there's some style, but the console was saying it couldn't get at the graphic files needed for the style.

I'm not sure what the best way is to reference a graphic file that's contained in the extensions directory from a css file so I just turned all the graphics into dataurl's and put them in the css file. You can use a tool like this one...

http://dataurl.net/#dataurlmaker

...to get that done.

Now we have a nice looking dialog.

manifest.json

{
"name":"JQuery UI Dialog",
"description":"https://stackoverflow.com/questions/13669762/chrome-extention-using-jquery-in-content-script-resolve-error-when-creating-dial",
"manifest_version":2,
"version":"2",
"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["jquery-1.8.3.min.js","jquery-ui.js","client.js"],
      "run_at":"document_end",
      "all_frames": true,
      "css":["jquery-ui-base64.css"]
    }
  ],
"web_accessible_resources": [
    "client.js","jquery-1.8.3.min.js","jquery-ui.js"
  ],
"permissions": [ 
        "unlimitedStorage",
        "http://*/",
        "<all_urls>",
        "tabs"
   ]
}

jquery-ui-base64.css
https://gist.github.com/4193693
Thought it might be a little to big to put here.

client.js

try {
  console.log("Starting to create tabel");

  var layerNode = document.createElement('div');
  layerNode.setAttribute('id', 'dialog');
  layerNode.setAttribute('title', 'Basic dialog');
  var pNode = document.createElement('p');
  pNode.innerHTML = "This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.";

  layerNode.appendChild(pNode);
  document.body.appendChild(layerNode);


  jq162 = jQuery.noConflict(true);
  (function($) {
    $(document).ready(function() {
      $("#dialog").dialog();
    });
  })(jq162);



} catch(e) {
  console.log("script in page exception in appendChild" + e);
  //alert(e);
}

EDIT
Using chromes i18n support we can change the urls for the images in the css so they point to the files in our extension.
https://stackoverflow.com/a/8864212/189093
So this...
url(images/ui-bg_flat_0_aaaaaa_40x100.png)
...becomes...
url(chrome-extension://__MSG_@@extension_id__/images/ui-bg_flat_0_aaaaaa_40x100.png)
and the path isnt relative anymore and the __MSG_@@extension_id__ gets replaced with the id of your extension.
Also, all the images used this way need to be declared in the web_accessible_resources part of your mainfest.
So, that part in your manifest ends up looking like this (notice I took out the three you had there, they dont need to be included anymore as their injected by the extension now)...

"web_accessible_resources": [
    "images/ui-bg_flat_75_ffffff_40x100.png","images/ui-icons_222222_256x240.png","images/ui-bg_highlight-soft_75_cccccc_1x100.png"
  ]

..Ive only included the files I needed to get my test working, you may need to add more. Check the console on the page the script is running and it will tell you what files you need to add.
Here's a link to the same css file used in my test with the urls updated to work this way...
https://gist.github.com/4195616

Upvotes: 5

user899205
user899205

Reputation:

When you call jQuery.noConflict then $ variable will not be defined.

But in script.js you are calling $(document) right after noConflict. I think you forgot a line (function($ after calling noConflict.

You have to change your code to something like this:

jq162 = jQuery.noConflict(true);
(function($){
    $(document).ready(function() {
       $("#dialog" ).dialog();
    });
})(jq162);

Upvotes: 0

Related Questions