Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 464
deprecated Avatar asked Sep 10 '11 19:09

deprecated


2 Answers

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;
      }  
    })();
like image 146
Michael Berkowski Avatar answered Nov 07 '22 11:11

Michael Berkowski


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.

like image 3
chuckles Avatar answered Nov 07 '22 11:11

chuckles