36

I have a bookmarklet that I've made and it loads a script from my server onto the users current page. However I have an if check in my script that if a condition is not met then no action is taken. However if the user then meets that condition then the code is run, but has caused there to be two sets of scripts inserted into their page. Can i prevent this?

 <a href="javascript: (function () {
    var jsCode = document.createElement('script');
    jsCode.setAttribute('src', 'http://xxx.co.uk/xxx/script.js');
  document.body.appendChild(jsCode);
 }());">Bookmarklet</a>
benhowdle89
  • 36,900
  • 69
  • 202
  • 331

7 Answers7

49

You can check whether your script is loaded like this:

function isMyScriptLoaded(url) {
    if (!url) url = "http://xxx.co.uk/xxx/script.js";
    var scripts = document.getElementsByTagName('script');
    for (var i = scripts.length; i--;) {
        if (scripts[i].src == url) return true;
    }
    return false;
}

Alternatively, you could do something like this:

<a href="javascript:
    if (!jsCode) {
        var jsCode = document.createElement('script');
        jsCode.setAttribute('src', 'http://xxx.co.uk/xxx/script.js');
        document.body.appendChild(jsCode);
    }
 ">Bookmarklet</a>

This "pollutes" the global namespace with the jsCode variable, but that might be a necessary evil. You could rename it to something that is unlikely to appear in the document where the bookmarklet is run.


Please note that while the javascript URI scheme is okay for bookmarklets as in this case, it's not considered to be a good practice for normal use.

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • Oh ok, what's the modern way to create bookmarklets now-a-days? – benhowdle89 Mar 11 '12 at 22:05
  • This is fine, I was missing the fact that it was a bookmarklet earlier... let me re-add that in a way that makes sense – Dagg Nabbit Mar 11 '12 at 22:10
  • Some scripts maybe add with a random query string at the end of the URL so an even better solution is to use the includes function instead of '==' operator. – Mousa Alfhaily Jul 26 '20 at 19:50
  • There is some danger in checking `scripts[i].src` if you reference internal sources. At least Chrome prepends "http://localhost/" in case that a relative path was used, e.g. `test.js`. I now use `scripts[i].getAttribute('src')` – HHFox Nov 23 '20 at 11:53
15

Just check the selector length. Here's an example using jQuery:

if ($('script[src="http://xxx.co.uk/xxx/script.js"]').length > 0) {
    //script exists
}
13

You can place id attributes on your script tags and use document.getElementById('your-id') to identify whether the script is on the page before adding.

if (!document.getElementById('your-id')) {
    // append your script to the document here, ensure it has its id attribute set to 'your-id'
}
Cord Rehn
  • 1,119
  • 14
  • 22
11

Solution with ES6, no jQuery:

const url = 'http://xxx.co.uk/xxx/script.js';

function scriptExists(url) {
  return document.querySelectorAll(`script[src="${url}"]`).length > 0;
}

if(scriptExists(url)) {
  ...
}

It's not recommended to inline JS into HTML. Instead add event listeners:

 function bookmark() {
   if(scriptExists(url)) {
     ...
   }
 }

 const button = document.querySelectorAll('a.bookmark');
 button.addEventListener('click', bookmark, false);
Jan Werkhoven
  • 2,656
  • 1
  • 22
  • 31
2

In case working with local and live alternatively.

The exact URL may change. I think the ID method is better.

This is a combination of Two StackOverflow answers.

if (!document.getElementById('your-id')) {
        addScript("your_script_src"); //adding script dynamically
        addCSSFile("your_css_src"); // adding css files
}

function addScript(path) {
        var head = document.getElementsByTagName("head")[0];
        var s = document.createElement("script");
        s.type = "text/javascript";
        s.src = path;
        s.id = "your-id";
        head.appendChild(s);
}

function addCSSFile(path) {
    var head = document.getElementsByTagName("head")[0];
    var s = document.createElement("style");
    s.type = "text/css";
    s.src = path;
    head.appendChild(s);
}
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
0
if (document.getElementById('element-id')) {
// if exist must do something 
}

hi, this is worked for me, please try it if you still need it

0

if you create a variable in the global scope (window.yourVariable) and check if that exists already then you can decide if you want to add your jsCode snippet code or run whatever you are running in script.js

voigtan
  • 8,953
  • 2
  • 29
  • 30