About user scripts in beta 3

, , , ,

NOTE: I've made a webpage now to present the user.js framework script. See <http://people.opera.com/rijk/opera/userjs.html>

Hallvord introduced Opera's latest surprise for tweakers in his Journal.

What is a user script

Basically it is a script from a local file that gets executed before any other scripts (or event handlers) on the page, once in every document.

I've collected some more or less interesting scripts that I'd like to run on all pages, and on specific sites, in this user script: <http://people.opera.com/rijk/opera/scripts/user.js>. I'm not yet using any versioning there BTW, it can be a different script tomorrow, or in an hour. The script is set up to easily add extra functions, and enable/disable them for all or for specific sites when you want. Don't expect me to explain specific functions, because I'm not a proficient JavaScripter myself. I'd say: experiment, share, and file bug reports if necessary.

Enabling user script in Opera 8 beta 3

[User Prefs]
User Javascript=1
User Javascript File=C:Program FilesOperauserjs.js

Security

The script has exactly the same restrictions as a script on the page, except that it can access some User JS specific functionality (we'll get back to you on that) and that it can read the text property on any script element (normal scripts can't read the text property of external scripts loaded from other servers than the document.)

The additional privileges are available when the User JS file is initially executed and when a User JS event is being handled. Global functions defined by User JS but called from a script in the page have no special privileges.

Add a 'BlogThis!' button to OperaHallvord unveils Opera's special User JavaScript events

Comments

Non-Tropponon-troppo Wednesday, March 16, 2005 9:22:11 PM

Rijk, thanks for the slow trickle of info coming through! A really nice surprise you all landed on us.

You have an error in your example path: User Javascript File=Crogram FilesOperauserjs.js

/me goes off to read through your user.js

Jordijor Wednesday, March 16, 2005 9:22:11 PM

That bug in the path is caused by the journal code.

Rijk Wednesday, March 16, 2005 9:22:11 PM

Fixed that by escaping the slash with a slash (reload if necessary to see the fix).

evaristeizzyo Wednesday, March 16, 2005 9:22:11 PM

I have the following function to clean all the (news - web sites) links out of Yahoo! News. The commented-out line should work but doesn't.
function yahooNewsCleanser(){
//document.body.innerHTML=document.body.innerHTML.replace(/ (<a(.*)a>)/g,'');
document.body.innerHTML=document.body.innerHTML.replace(/ ((.*)news(.*) - (.*)web sites(.*))/g,'');
}

evaristeizzyo Wednesday, March 16, 2005 9:22:11 PM

domainHandler['news.yahoo.com'] = yahooNewsCleanser;
and try it here, for instance: http://story.news.yahoo.com/news?tmpl=story&amp;cid=519&amp;ncid=716&amp;e=4&amp;u=/ap/20050317/ap_on_re_us/laci_peterson

evaristeizzyo Wednesday, March 16, 2005 9:22:11 PM

The journal code stripped out some of my slashes; the parentheses that I'm searching for are properly escaped with backslashes in my actual code.

Rijk Wednesday, March 16, 2005 9:22:11 PM

But I'm not even sure what you are trying to achieve. And as I said, I'm no JavaScript expert.

scipio Wednesday, March 16, 2005 9:22:11 PM

Something tells me this could be used to kill target="_blank"s... sherlock

scipio Wednesday, March 16, 2005 9:22:11 PM

"/me goes off to read through your user.js"

I've found the useful function called bodyIDforAll() in your user.js. Can you perhaps explain what the following piece of code is supposed to do?

--code--
.replace(/^d/,'_$&')
--------

scipio Wednesday, March 16, 2005 9:22:11 PM

Heh... somebody thought of that already. It's in Rijk's example.

Rijk Wednesday, March 16, 2005 9:22:11 PM

Let's see if i can find that back, I got it via Robert B's Journal...

Here it is:
http://my.opera.com/quiris/journal/54 points to http://my.opera.com/forums/showthread.php?s=&amp;postid=842398#post842333

"Above code generates CSS signuture for every entire site which lack such ID.
Rules:
- every dot in domain name is replaced with hyphen
- domain names started with count at beginning are started with underscore at beginning of css signature
- www. is cut off"

The part you asked about is the regular expression to replace a number with a underscore+number, because ID values are bot allowed to start with a number.

evaristeizzyo Wednesday, March 16, 2005 9:22:11 PM

Rijk-it's simply a regular expression to replace all the (&lt;a href="blah"&gt;news&lt;/a&gt; - &lt;a href="blah"&gt;web sites&lt;/a&gt;) links that Yahoo!'s content management system peppers its news stories with nothing. I hate the stupid (news - web sites) links :-) The regular expression that doesn't work searches for the string " (<a" followed by any number of any character followed by "/a>)", which should capture all the (news) and (news - web sites) links. but it doesn't actually work, for some reason, so I had to write a more complicated regex that looks for "(" followed by any number of anything followed by "news" followed by any number of anything followed by " - " followed by any number of anything followed by "web sites" followed by any number of anything followed by ")" and replace it with nothing, cleaning up the text. It's fine, but I'm disturbed that I can't refer to tags directly in my valid (I tested it) regular expression. Is it because of the character &lt;? Does that get ignored by the user javascript's regex engine?

evaristeizzyo Wednesday, March 16, 2005 9:22:11 PM

Oops. I guess I could have simply used < and >, eh?

Friedrich Wednesday, March 16, 2005 9:22:11 PM

Would it be possible to create a script that kills a tab if it is both empty and doesn't have focus? What I'm trying to get is autoclose of those annoying blank windows when saving files - or is there maybe a more intelligent approach for it?

Friedrich

Idan AdarYtseJam Wednesday, March 16, 2005 9:22:11 PM

Can multiple scripts be added? user.js, test.js and etc?

Mark SchenkMarkSchenk Wednesday, March 16, 2005 9:22:11 PM

If I a not mistaken it means that if a URL starts with a number (/^d) it is replaced by a '_' followed by the actual number.

Mark SchenkMarkSchenk Wednesday, March 16, 2005 9:22:11 PM

Using Rijk's user.js as a basis, I have written some scripts of my own. The ones I consider generally useful, I will store here:

http://www.markschenk.com/webdesign/userjs/

Currently there are only two. The first is useful on W3C specs, and will make linking to specific areas in the spec useful. It will add links to the headers, so you just click on the header and the URL can be found in the addressbar.

The other is only useful for Dutch users, because it fixes a rendering error on www.nu.nl

Have fun!

Rijk Wednesday, March 16, 2005 9:22:11 PM

Nope. You can change the names on your computer, and then reload the webpage, for easy testing.

Rijk Wednesday, March 16, 2005 9:22:11 PM

Friedrich, I don't think that is possible. Such empty pages contain no document at all, so the script has nothing to work on.

The blank-page issue is something that needs to be fixed by the Opera developers. I've been told it is not as easy as it looks, but a fix would be appreciated by users!

Aaron Boodmanboogs Wednesday, March 16, 2005 9:22:11 PM

Hi Rijk,

Did you consider supporting greasemonkey's existing distribution model with the metadata header and installing separate userscripts (http://greasemonkey.mozdev.org/authoring.html)?

It would be really cool if we could share scripts between the two browsers.

-- Aaron Boodman (the greasemonkey guy)

Rijk Wednesday, March 16, 2005 9:22:11 PM

Hi Boogs,

First of all: I'm not the developer smile

Currently Opera doesn't have the capability to store multiple scripts and tie them to specific sites, so interoperability is not yet feasable. That is why I hacked together my user.js framework script. From what I've seen, the Greasemonkey scripts that don't use XPath should be perfectly usable in Opera. Already I've added some of them to my example userscript (with attribution of course).

I'm sure our developers know about Greasemonkey. But I don't know much about our plans for future development in this area, and what little I know is probably NDA'd. But I'll ask the responsible developer about this.

Nicolas Mendozanicomen Wednesday, March 16, 2005 9:22:11 PM

I take it you want a subdomain functionality. Fear not I needed it myself and added it quickly:

yahoo.com or news.yahoo.com will now match story.news.yahoo.com


function loadHandler() {

// Here we set a variable that holds the full path:
var
l=window.location,
fullpath=l.hostname+(l.port!=''?':'+l.port:'')+l.pathname;

if(window==window.top){
// Here we check if the current full path has a handler defined,
// and, if that is the case, run that handler function:
if(fullpath in pathHandler)
pathHandler[fullpath]();
// Here we check if the current domain has a handler defined,
// and, if that is the case, run that handler function:
for(dom in domainHandler) {
var pat = new RegExp(dom+"$")
if (pat.test(document.domain)) {
domainHandler[dom]();
}
}
// Here we run the functions for all pages:
while(allHandler.length>0)
allHandler.shift()();
}
}
// End of loadHandler function, all handlers are called.
// Mission accomplished, return to base.

Friedrich Wednesday, March 16, 2005 9:22:11 PM

Are the new in-line error messages documents, technically? Is it possible to apply user JS to them?

Jordijor Wednesday, March 16, 2005 9:22:11 PM

Hello Rijk, I am getting a HTTP 500 error on http://people.opera.com/rijk/opera/scripts/user.js

Is it still available?

Rijk Wednesday, March 16, 2005 9:22:11 PM

It's back. I was making some changes, and forgot to upload using the right name. The script is smaller now, and selects on domain instead of server (thanks Nicomen). I'll create a bigger demo later.

Rijk Wednesday, March 16, 2005 9:22:11 PM

Yes, these are documents. Use of 'View source' reveals they've already been fitted with IDs on the BODY element for easy user styling.

Friedrich Wednesday, March 16, 2005 9:22:11 PM

GREAT!

So, would the following be possible: As long as the error message is displayed, initiate a reload every ten seconds (essentially a "retry till success" script)?

In any case, this means we can (kinda a hack, but it would work, wouldn't it? I don't really know Javascript.) customize our error messages, can't we?

Rijk Wednesday, March 16, 2005 9:22:11 PM

Yep, should be possible. I'm no Javascript guru either, maybe you can post a message in the Customize Opera forum.

Non-Tropponon-troppo Wednesday, March 16, 2005 9:22:11 PM

The only way Opera can do that at the moment is to wrap user javascript in some kind of API (kind of how Rijk does it now), which could parse your metaadata formating to input into the domain handling routines. As we cannot pull in seperate files, this would either need manual additions OR a web application (we've thought about a combined repository and user js manager) to roll up greasemonkey scripts selected by a user automatically into a single user.js file...

Non-Tropponon-troppo Wednesday, March 16, 2005 9:22:11 PM

Rijk, It is fairly easy to add a messaging system so you can see which functions trigger on which pages

1. Initialise a variable at the beginning of Rijk's script:

var notify='';

2. Add the following function to the function list:

function ScriptStatus() {
window.defaultStatus=notify;
}

3. Add the function as the last but 1 option on the allHandler list, like:

allHandler=[
bodyIDforAll,
killBlank,
ScriptStatus, //here it is
doNothing];

4. To each function add something like this as the last line

notify += '-Unique name-';

so for e.g.

// 'backgroundToGreen' can be used to test if the user script is working.
function backgroundToGreen(){
document.body.style.background = "green";
notify += '-Green-';
}

This will let you see which functions are activated for the page by providing the info in the status bar. Commenting out the line in allHandler can then turn messaging on/off

scipio Wednesday, March 16, 2005 9:22:11 PM

"Compensating for Nu.nl stupidity", huh? smile I did the same for Trouw.nl: http://my.opera.com/scipio/journal/4

scipio Wednesday, March 16, 2005 9:22:11 PM

I've been trying to figure out what the best way is to add the events Hallvord mentioned in his journal (http://my.opera.com/hallvors/journal/45) to the framework provided bij Rijk... Has anyone been thinking about that, too?

ILoveJD Wednesday, March 16, 2005 9:22:11 PM

Can't remember the URL, but someone had an idea a while back to give each site a body id tag identifying just that site (eg "www-ilovejackdaniels-com"). That allowed you to create a custom user style sheet just for that site. Very slick.

The problem with that, and the reason not many people caught on to it, was that not many web site developers added the tag to their sites.

This addition to Opera 8 should mean that you can set a script to run when you load a site to automatically give the body tag this ID. Then, it's fairly easy to (if you wanted to) define custom styles to apply to only that site, using the body id tag.

For example, Yahoo's interface is a bit of a mess. The user.js file could add 'id="www-yahoo-com"' to the body tag of all yahoo pages. Then in your user style sheet you could define styles just for yahoo, like so:

#www-yahoo.com * {
font-family: Georgia;
}

Write a comment

You must be logged in to write a comment. If you're not a registered member, please sign up.