deprecated
deprecated

Reputation: 5252

How to enforce a bookmarklet to run only once?

My bookmarklet consist of a call to a 'launcher' script that is inserted into body. As it runs, it inserts in a similar way more scripts (jQuery, the actual application), and a CSS.

Bookmarklet

javascript:(function(){
    var l = document.createElement('script');
    l.setAttribute('type','text/javascript');
    l.setAttribute('src','launcher.js');
    document.body.appendChild(l);
})();

Launcher.js

var s = document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','my actual script');
document.body.appendChild(s);

// I repeat a block like this once per script/css.

The problem is that if the bookmarklet is clicked twice, all the scripts will be inserted again. How can I prevent this behavior?

Upvotes: 7

Views: 728

Answers (3)

chuckles
chuckles

Reputation: 226

I found the cleanest way for me to do this was to name the function that loads the external js file, the same name as a function inside the external file that I want to be ran everytime the user clicks the bookmarklet. This way when the bookmarklet is clicked the first time, it loads the external file and on subsquent clicks a function in the external file is ran.

Here is some sudo code:

This would be the code in the url of the bookmarklet link

if( ! bookmarklet){
    var bookmarklet = {
     click: function(){
         js = document.createElement('SCRIPT');
         js.type = 'text/javascript';
         js.src = 'http://external.js?' + (Math.random());
         document.getElementsByTagName('head')[0].appendChild(js);
     }
   };
}
bookmarklet.click(); // this will be called everytime the bookmarklet is clicked

The external.js file would contain a function with the same name like this:

var bookmarklet = {
    click:function(){
         // insert logic you want to run every time the bookmarklet is clicked
    }
};
bookmarket.click(); // run once after file is loaded

This way when the external file is loaded your function (example function is bookmarklet.click) now runs the function inside the externally loaded file and will not load the external js file a second time.

Upvotes: 3

Michael Berkowski
Michael Berkowski

Reputation: 270727

You can set a property on the window object which is oddly named, so it is unlikely to cause namespace collisions, on the first run only. On subsequent runs, the code will not execute if the property is present:

    javascript:(function(){
      // Test for existence of your weird property
      if (!window.hasOwnProperty('yourWeirdPropertyX774x9ZZYy4')) {

          // Run all your existing code
          var l = document.createElement('script');
          l.setAttribute('type','text/javascript');
          l.setAttribute('src','launcher.js');
          document.body.appendChild(l);

         // Set the flag so this won't run again
         window.yourWeirdPropertyX774x9ZZYy4 = true;
      }  
    })();

Upvotes: 4

Joe
Joe

Reputation: 15812

Simplest/Cleanest way to implement singleton in JavaScript?

An example on a good way to implement Singletons in JS. I won't copy/paste his answer, but give it a good read :)

Upvotes: 0

Related Questions