Another Auto Update Script

By sizzlemctwizzle Last update Feb 11, 2011 — Installed 15,480 times.

A little help?

in
Subscribe to A little help? 33 posts, 4 voices



Momentum Scriptwright

I'm trying to use this script in a script I'm writing, but it's not working. I've formatted my script like

(function() {try {
//MY SCRIPT HERE
} catch(e) {dump('Error ('+e.lineNumber+'): '+e+'\n')} })

I can't figure out how to get the auto updater to work within this script. If I remove 'function() {...})' and place the auto updater script first, like

//AUTO UPDATER
try {
//SCRIPT HERE
} catch(e) {dump('Error ('+e.lineNumber+'): '+e+'\n')}

it works, but I'd rather not expose my function like that. Is there a way to work around this? I've also tried placing it within the function itself, like

(function() {try {
//AUTO UPDATER
//MY SCRIPT HERE
} catch(e) {dump('Error ('+e.lineNumber+'): '+e+'\n')} })

Thanks for your help!

 
sizzlemctwizzle Script's Author

I have no clue what you are talking about. This works perfectly. Check for updates manually through the user script commands menu to see that it does work. I also don't know what you mean by that you'd rather not expose your function. Greasemonkey already wraps all your code in an anonymous function.

(function() {try {
// Copyleft Michael Medley <medleymind@gmail.com>, All Wrongs Reserved
CheckScriptForUpdate = {
  // Config values, change these to match your script
 name: 'IC Map Links', // Script Name
 version: '0.0.6', // Version
 id: '37813', // Script id on Userscripts.org
 days: 2, // Days to wait between update checks

 // Don't edit after this line unless you know what you're doing :-)
 time: Math.round(new Date().getTime() / 1000),
 call: function(response) {
    GM_xmlhttpRequest({
      method: 'GET',
	  url: 'http://userscripts.org/scripts/source/'+this.id+'.meta.js',
	  headers: {
	  'User-agent': window.navigator.userAgent,
	    'Accept': 'application/atom+xml,application/xml,text/xml',
	    },
	  version: this.version,
	  time: this.time,
	  name: this.name,
	  response: response,
	  onload: function(xpr) {
	  this.src_version=/@version\s*(.*)\s*\n/i.exec(xpr.responseText);
	  this.src_name=/@name\s*(.*)\s*\n/i.exec(xpr.responseText);
	  if ( (this.src_version[1] != this.version) && (confirm('A new version of the '+this.src_name[1]+' user script is available. Do you want to update?')) ) {
	    GM_setValue('updated', this.time);
	    document.location.href = 'http://userscripts.org/scripts/source/'+this.id+'.user.js';
	  } else if ( (this.src_version[1]) && (this.src_version[1] != this.version) ) {
	    if(confirm('Do you want to turn off auto updating for this script?')) {
	      GM_setValue('updated', 'off');
	      GM_registerMenuCommand("Auto Update "+this.name, function(){GM_setValue('updated', Math.round(new Date().getTime() / 1000));CheckScriptForUpdate.call('return');});
	    } else {
	      GM_setValue('updated', this.time);
	    }
	  } else {
	    if(this.response == 'return') alert('No updates available for '+this.name);
	    GM_setValue('updated', this.time);
	  }
	}
      });
  },
 check: function() {
if (GM_getValue('updated', 0) == 0) GM_setValue('updated', this.time);
    if ( (this.time > (GM_getValue('updated', 0) + (60*60*24*this.days))) && (GM_getValue('updated', 0) != 'off') ) {
      this.call('none');
    } else if (GM_getValue('updated', 0) == 'off') {
      GM_registerMenuCommand("Auto Update "+this.name, function(){GM_setValue('updated', Math.round(new Date().getTime() / 1000));CheckScriptForUpdate.call('return');});
    } else {
      GM_registerMenuCommand("Check "+this.name+" for updates", function(){GM_setValue('updated', Math.round(new Date().getTime() / 1000));CheckScriptForUpdate.call('return');});
    }
    }
};
CheckScriptForUpdate.check();
//YOUR SCRIPT HERE
} catch(e) {dump('Error ('+e.lineNumber+'): '+e+'\n')} })();

 
Momentum Scriptwright

So I got it to work but I still have a bug:

document.location.href = 'http://userscripts.org/scripts/source/'+this.id+'.user.js';

doesn't work but

document.location.href = 'http://userscripts.org/scripts/source/38092.user.js';

works just fine. I don't know how this can be, because this.id works in other places. But when I add

GM_log('http://userscripts.org/scripts/source/'+this.id+'.user.js')

I get '.../undefined.user.js'. Finally, I get an alert with this message:

Error loading user script:
404: Not Found

Thanks again for your help, it's a great little script.

 
sizzlemctwizzle Script's Author

Thanks for reminding me that I can be a real idiot sometimes. I made the fix and updated the script. Just copy the code again or you can look at the difference file and make the change yourself. Sorry about that.

 
sizzlemctwizzle Script's Author

You might also want to look out for another update in the near future to this script. Jesse has promised to make some changes to the site that will help to facilitate a new method of checking for updates. Essentially you would just copy my code into your script and you wouldn't have to do any configuration and when you make updates to your scripts you won't even have to update the version number.

 
Momentum Scriptwright

Looks great. Maybe I'll just install your script, and when it tells me I need to update it I can update my scripts as well.

One suggestion, tho: might you want to include something like "Automatic updates can be re-enabled for this script under User Script Commands." after "Do you want to turn off auto updating for this script?" I only realized that the menu commands were there because I saw them in the source code. If I never looked at it, I would have had no idea how to re-enable updates.

 
Momentum Scriptwright

One last problem:

Greasemonkey doesn't recognize scripts opening within frames. It simply navigates to the source code, and doesn't ask to install. Can the script be called to open in a new tab? would that make a new tab?

 
Momentum Scriptwright

Nevermind, I figured it out. You need to change

document.location.href = 'http://userscripts.org/scripts/source/'+this.id+'.user.js';

to

javascript:top.location = 'http://userscripts.org/scripts/source/'+this.id+'.user.js';

I don't know if it's worth changing this permanently, but it doesn't seem to mess things up normally, either.

 
sizzlemctwizzle Script's Author

Thank you for your useful suggestions. I have added a dialog about re-enabling and updates now open in a new tab(there's an Api method for this).

 
Momentum Scriptwright

The problem with the GM API is that it will open a blank tab when updating the script.

 
sizzlemctwizzle Script's Author

How about I wrap the object with
if (self.location == top.location) { /* Update code */ }
that way it won't even check for updates within an iframe anyway?

Edit: Yeah I'm going to do that. I also have another update I've been meaning to make and I promise after that I'll be done updating for awhile lol.

 
sizzlemctwizzle Script's Author

Alright, there you go. I think that really cleaned it up some. My OCD can rest for the night now. Hopefully that will do for awhile lol. Thanks for all of your help. I appreciate the feedback.

 
Momentum Scriptwright

Now it just throws me errors =/

You forgot a comma, for one, but even when that's in it says this.compare's not a function.

 
sizzlemctwizzle Script's Author

Damn it. I just shouldn't try to make updates at 4am anymore. Well I'm debugging it right now and the last thing that has got me stuck is that it keep throwing me an error when I try to redirect to the install url. I might need to get a little creative.

 
sizzlemctwizzle Script's Author

Okay. All bugs have been fixed and there are no more errors. I made sure EVERYTHING was working properly this time. I reverted to the GM_openInTab('http://userscripts.org/scripts/source/'+this.id+'.user.js'); method because as far as I can tell Greasemonkey will throw an error when you try to redirect to a install url. Yes it does open a blank tab in the background, but you'll just have to ignore that. There is no other way to install without getting an error. I hope you still find the script useful and I'm sorry for all the problems that have been occurring.

 
Momentum Scriptwright

It's a great script and I'm glad I could help out. One more question:

Why do you use version: this.version, time: this.time then call this.version and this.time rather than just calling CheckScriptForUpdate.version and CheckScriptForUpdate.time?

 
sizzlemctwizzle Script's Author

I've gotten rid of version: this.version, time: this.time but I call this.time instead of CheckScriptForUpdate.time because it's shorter. Good question though. Sometimes it does cause some accidental problems so maybe it's more trouble than its worth.

 
Momentum Scriptwright

Thanks! I'm relatively new to JavaScript (in fact I just got into it in the last two weeks or so) so I was wondering if there was a benefit to that, like efficiency or something, or not. It was definitely giving me some problems in one of my own scripts.

 
sizzlemctwizzle Script's Author

Well lets say I called CheckScriptForUpdate.time maybe twenty times in my script. Then I decide to change the name of my object from CheckScriptForUpdate to AnotherUpdater. Then I would have to go through my script and change all twenty instances of CheckScriptForUpdate.time to AnotherUpdater.time. If I had used this.time I wouldn't have to change a thing. Plus I guess there is always efficiency is having your script be as sort as possible. But that is only a very trivial use of this

I'm really surprised that you're new! Your IC Map Links script is very well written for a beginner. You make my first user script look absolutely pathetic. I've been writing Javascript for a little over a year and a half. I use to write a lot of PHP (I crashed my host server a couple times lol). I would say that I'm a pretty poor scriptwriter. I'm just too hackerish. I have no problems getting things to work its just my scripts are usually messy, poorly organized, and inefficient. I make a lot of stupid mistakes, but I improve my methods and ability with every script I write so I guess practice makes perfect.

 
Momentum Scriptwright

Your script still calls for an update only if it's in the top frame, but I think this is unnecessary because you're opening a new tab.

Also, will this script cause errors in Opera? I know you can't get it to work (at least easily), but it would be nice if it would simply not run if in Opera, instead of throwing errors.

 
sizzlemctwizzle Script's Author

No its not unnecessary because it would be executed multiple times if it ran in iframes.

Yes it will cause errors in Opera because there is no support for GM_xmlhttpRequest, but this is a Greasemonkey userscript. I don't write scripts for Opera. However you could change
if (self.location == top.location) CheckScriptForUpdate.check();
to
if (self.location == top.location) && (GM_xmlhttpRequest) CheckScriptForUpdate.check(); and that would stop it from running outside of Greasemonkey.

 
Momentum Scriptwright

Alright. I figured as much. I know you don't write scripts for Opera, but it would be nice to be able to include this (non-functionally) in Opera compatible scripts as well. Perhaps just adding the test to your next version? Of course I can always add it in myself.

 
Swashata Scriptwright

Thank you! I will test and reply here :)

 
sizzlemctwizzle Script's Author

Thank you! I will test and reply here :)

Good. I always love to hear from people who use my code. I'm currently using this code in the majority of my user scripts.

 
Swashata Scriptwright

Thanks a Lot for correcting my mistakes!! I will reply ASAP! :) Your work is really appreciable :)

Cross
Presentational HTML allowed.
Use <code> for inline code and <pre> for code blocks. Use &lt; and &gt; for literal < and >.
We help break paragraphs and link your links.
or cancel