web:config

tips and tricks for the interwebs

Subscribe to RSS feed

Sticky post

typical disclaimer

So, you're interested in javascript and other related matters? Then this blog might interest you.
However, please do note that this is a personal blog, maintained solely by me and not endorsed by any other 3rd party, included any employer of mine. So if I feel like bashing some multibillion dollar company, or a community of fanboys, that's my personal rant alone. The same applies to everything I write on this website, namely forums.

All user scripts I offer are obviously free of charge and devoid of any malicious code that might harm the user in anyway, like stealing data. I WILL NOT in any case build a script that harms users. I have the utmost respect for whom uses my scripts, and I hope they will improve whatever you feel like needs to be improved.
However, I will not be held liable for any harm or problems the script might cause to you, probably due to bugs or non foreseen situations. So use the scripts at your own will and risk. They still have my personal guarantee of quality.

So, to finish, I hope you'll find useful resources here, and learn a few things. I hope you have as much fun using my stuff as I had building them. Have fun!

The cookie monster

, , ,

Typical problem when cooking a user script: "I want to control which cookies the website sets."

Given that document.cookie is a property, the way to go is using getters and setters.

Read more...

chrome me not

, ,

Now that There is a public Opera build with extension support, users might want to poke at the code of other extensions for other browsers. Notably, the Chrome extension website does not provide download links for the extensions if you're not using Chrome or Chromium. Hence I coded a user script which enables the Install button in Opera, and prompts the user to save the file. So, then you just need to open it with a program that understands zip files.

chrome-extension-download.js

Have fun.

Opera is web store

,

Opera 10.50 (long, long ago) got us Web Storage and Web SQL Databases to play with. Tools > Advanced > Storage, opera:webstorage and opera:webdatabases are handy to check where's your data but there's no way to inspect it but to open the site and use a bookmarklet [1] or open dragonfly. So I cooked up a bash script that lists Opera's Web Storage data, and which also opens the Web SQL Database data files directly in sqlite, if you have it available. Get it at ls-storage
$ ls-storage
Found 4 sites. Which to list? ENTER (all), q (quit)
0: file://localhost
1: http://blog.quplo.com
2: https://dragonfly.opera.com
3: http://videojs.com
0
Reading pstorage/00/11/00000000 of origin file://localhost
a: 1234
$ ls-storage -h
Usage: ls-storage [options]
 By default lists all localStorage areas available and their contents.
Interactively prompts for which storage area to show

Options:
 -h            Show this help
 -p            path to profile folder
 -l            List only localStorage
 -u            List only UserJS storage
 -d            List Web Databases

Remarks:
 The options l, u and d override each other.
 When listing web databases, one must be forcefully choosen
and then sqlite will be executed with the proper data file.
[*] Title pun kindly borrowed from Mongo DB is web scale [1] Bookmarklet (works everywhere)
javascript:(function(){function _(){for(var i=0,m=arguments.length;i<m;i++)h.push(arguments[i]);}function htmlize(s){return s!=null?String(s).replace(/[<>&]/g,function(a){return htmlize.chars[a]}):String(s);};htmlize.chars={'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'};var h=['<style>table{border-collapse:collapse;}td{border:1px solid black;padding:4px}</style>'];_ ('<h1>Storage for ',location.protocol,location.host?'//':'',location.host,'</h1>');for(var i=0,ns=['localStorage','sessionStorage','preferences'],n,h,o;n=ns[i];i++){o=window[n]||(window.widget&&widget[n]);if(!o)continue;if(o.length){_ ('<h1>',n,'</h1><table><tr><th>Key</th><th>Value</th><th></th></tr>');for(var j=0,m=o.length,k,v;j<m;j++){k=o.key(j);v=o.getItem(k);_ ('<tr><td>',htmlize(k),'</td><td>',htmlize(v),'</td><td><button onclick="Storage.prototype.removeItem.call(opener.',n,',\'',htmlize(k),'\');var p=this.parentNode.parentNode;p.parentNode.removeChild(p);">Delete</button></td></tr>');}_ ('</table><p><button onclick="Storage.prototype.clear.call(opener.',n,');">Clear All?</button></p>');}else{_ ('<h1>',n,'</h1><p>No data</p>');}}var o=open('about:blank','storagedump','');o.document.write(h.join(''));if(document.domain!=location.hostname)o.document.domain=document.domain;})();
;
Full code
(function(){
  function _(){ for(var i = 0, m = arguments.length; i < m; i++) h.push(arguments[i]); }
  function htmlize(s){ return s != null ? String(s).replace(/[<>&]/g,function(a){return htmlize.chars[a]}) : String(s); };
  htmlize.chars = {'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;'};
  var h = ['<style>table{border-collapse:collapse;}td{border:1px solid black;padding:4px}</style>'];
  _ ('<h1>Storage for ', location.protocol, location.host ? '//' : '', location.host, '</h1>');
  for(var i = 0, ns = ['localStorage', 'sessionStorage', 'preferences'], n, h, o; n = ns[i]; i++)
  {
    o = window[n] || (window.widget && widget[n]);
    if (!o) continue;
    if (o.length)
    {
      _ ('<h1>', n, '</h1><table><tr><th>Key</th><th>Value</th><th></th></tr>');
      for(var j = 0, m = o.length, k, v; j < m; j++)
      {
        k = o.key(j);
        v = o.getItem(k);
        _ ('<tr><td>', htmlize(k), '</td><td>', htmlize(v), '</td><td>[html:button onclick="Storage.prototype.removeItem.call(opener.', n,
          ', \'', htmlize(k), '\');var p=this.parentNode.parentNode;p.parentNode.removeChild(p);"]Delete</button></td></tr>');
      }
      _ ('</table><p><button onclick="Storage.prototype.clear.call(opener.', n, ');">Clear All ?</button></p>');
    }
    else
    {
      _ ('<h1>', n, '</h1><p>No data</p>');
    }
  }
  var o = open('about:blank','storagedump','');
  o.document.write(h.join(''));
  if (document.domain != location.hostname)
    o.document.domain = document.domain;
})();

Hva heter jeg ?

, ,

One of the interesting things of moving abroad is that something trivially simple in our home country, like pronouncing your name, can be a challenge to a foreigner sherlock

My name, João, is one of the most popular names in Portugal. You kick a stone and find someone with that name under it. It's the equivalent of John (english), Juan (spanish), Jean (french), Johan (norwegian). It's pronounced like this http://forvo.com/word/joão/.

People pronounce it in all possible imaginable ways: iaua, ioau, joau, ioa, joe, which is both funny and annoying. For me, misspelling someone's name is very rude, so I always try to get them right. I find it equally rude, if the other person doesn't even bother to do the minimal effort to get the name right, or bother to ask first, or misspell it over and over again. How hard would it be to show some personal courtesy ? [1]

Maybe I should invent a name tag with a loud speaker, or key card, name tag, loud speaker combo. yes

I wonder what d.i.z. has to say ?

Ha det!

[1] This is not a rant again someone, just an interesting observation about moving abroad

backup your profile

Hi !
Backing up your profile is recommended when you're upgrading Opera or trying snapshots. However, the process of opening the file manager, selecting the profile folder contents except the cache folders and other superfluous content is tedious and boring.
It's much more easy to just open a terminal and type
$ backup-opera-profile
and for that I did the following bash script, linux only currently.

backup-opera-profile

It has a few usage options
~$ backup-opera-profile -h
Usage: backup-opera-profile [options] [archive name]

  -h, --help     Shows this help

  [archive name] Archive name (tar gzipped) where the profile content
                 will be saved. Value is optional. If not supplied a
                 name will be generated using the current date for
                 uniqueness. If -r is specified, the profile is restored
                 from the archive, and the archive name is mandatory.
                 The later action cannot be undone

  -d, --dry      dry mode. Does not create/change any files,
                 just displays what would happen

  -r, --restore  Restores profile from 'archive name'.
                 'archive name' argument becomes mandatory

  -p, --prefix   Parameter must be followed by profile folder name.
                 If ommited '.opera' is used. If the prefix is not
                 an absolute path, then it'll beresolved against the
                 user's home folder, not the current working folder
Example:
  $ backup-opera-profile
or
  $ backup-opera-profile -p .opera-weekly -r backup-20080524.tgz

So, now you don't have an excuse to always have the latest snapshot installed p

a better quicktime

, , ,

Hi !
Linux users have traditionally been plagued from deliberate lack of support from many big companies for Linux.
In the current particular case, Apple has never done QuickTime for Linux, and I'm happy they never did. People argue about QuickTime being one of the worst softwares done by Apple. But back on the matter, not having the QuickTime plugin means that webpages that actually check for it will not work. Fortunately, this situation is not THAT common.
However, it exists, for instance, Apple's movie trailers website.
So, what should Linux users do (and Windows users which do not have QuickTime installed) ?

I made a really simple script, which detects if the QuickTime plugin is installed, and if it's not, it just creates an entry on navigator.plugins with a fake QuickTime, and it works great. Note however, that if the webpage tries to manipulate the plugin with scripting, it will most likely fail, because the plugin used by the browser might not support QuickTime's scripting API..

Download here:
xerath-add-quicktime-plugin.js
You can test it on the link above.

Have fun!

EDIT: clarification - you need to have another plugin that can handle QuickTime, like the VLC plugin.

gallery crawler

, , ,

This time I have a really simple script, which I did long time ago. But, it's very useful nonetheless.
How many times did you go image galleries, and had to flip through links, ads and poor page design to browse the gallery?
Unfortunately that's quite common. But, it's also quite common for pictures to be numbered sequentially.
For these cases I have the following solution:


The script adds that small menu, only visible if hovered (so it won't cover the image), and the keyboard also works. n goes to the next, p to the previous.
So, if you like the idea, download the script from
xerath-gallery-next.js

Have fun ! smile

EDIT (03-June-2009): I did a small update because images were dissapearing sometimes in imageshack. You may re-fetch the script

EDIT (02-Jan-2010): Fixed reference to helper function that was not included in the script, hence it broke for many other users.

for heavy duty posters

, , , ...

I present you with a new script to enhance user experience on my.opera, dubbed Scribit.

The script provides the user the hability to edit all his/her forum posts, blog posts and comments, dev.opera comments and widget discussion's page comments without the need of opening a new webpage with the edit form. The script will create a inline editor, that will replace the original post, or comment, so the user can edit it inplace, therefore making editions much more pleasant and quick. The script also displays a inline toolbar with all the available formatting commands used to produce bbcode. The toolbar is not only displayed in the inline editor, but also in the already existing reply boxes in the forums, blogs and at dev.opera.

This script initially only worked for forum posts and was very simple. I coded version 2.0, to submit to the User Javascript contest but by influence of the others the script never got to the juri's inbox. Oh well...

Screenshot with default setup (standard skin)

Screenshot of Quick Edit link

Screenshot of post quick editing (Oxygen skin)

Instructions
The following keyboard shortcuts are supported in the inline editor, producing bbcode formating. Press Ctrl plus any of the following keys:
  • b - bold
  • i - italic
  • u - underline
  • s - strikethrough
  • p - preformatted code
  • t - insert unordered list
  • l - align text to the left
  • g - center text
  • r - align text to the right
  • j - justify text
  • m - insert image
  • h - create hyperlink
  • e - insert email link
  • f - attach file
  • q - format text as quote
  • w - whisper text
  • ENTER - submit post
Later on, I'll make these easier customizable.

The script's configuration has sensible defaults. The entire UI is drawn using the current Opera skin, therefore providing an extra integration with the browser. Note however, that some skin bugs might be releaved. This script was succcessfully tested with Opera's default skin, and some other popular skins.
You can tweak the editor's behavior, although you need to edit the script itself.

This script does a daily new version check, warning the user of the new script version. You can disable this feature though. Check the configuration kCheckForNewVersion.

This entire script was done by me from scratch. The version check code was imported from the myopera-enhancements script, also made by me, and Robin Zalek. I recomend you to check it out. cool
http://my.opera.com/xErath/blog/2009/02/10/my-opera-community-enhancements

Credit also for AyushJ's quick-reply script for some inspiration. wizard
http://my.opera.com/community/forums/topic.dml?id=185091

Many thanks to Lars Kleinschmidt as well for testing and feedback. wink

However, the script has much to catch up. The roadmap is:
  • finishing html editing support yikes
  • supporting html to bbcode convertion and back on the fly
  • adding a 'remove formatting button', trivial for html, hard for bbcode knight
  • removing all prompt boxes and replacing them with proper floating
  • menus providing the user input suggestions, like listing his/her files when the attach button is pressed.
  • replacing the default new blog post, new form thread, and new dev opera article
  • making a lovely UI to edit configurations

Etimology: Scribit derives from scribe spock

Download the script from:
xerath-myopera-scribit.js
Future versions will be announced here, and the script will notify the user of the new version.

For the geeks
Script documentation is available at, generated using JSDoc:
scribit-documentation.zip

All text strings stored by this script are properly grouped to ease the script's localization. Currently, the suported languages are english and portuguese. Other users are encouraged to contribute. The language is autodetected and will match your UI language, but this can be overriden by setting the kPreferedLanguage configuration variable. If the UI language is not supported, english will be used.

Translations code chunk:
var translations = {
    en:{//plain english 
        L_SUBMIT: 'Submit',
        L_CANCEL: 'Cancel',
        L_QUICK_EDIT: 'Quick edit',
        L_QUICK_EDIT_LINK_TOOLTIP: 'Quick edit this post using inline editor',
        L_ERROR_ON_LOAD: 'Error loading post from server',
        L_LOADING_DATA_STATUS_MSG: 'Loading data from server...',
        L_POST_NOT_CHANGED_NOTIF: 'Post not changed (to quit press Cancel)',
        L_SUBMITTING: 'Submitting...',
        L_ERROR: a'Error',
        ...

Have fun! cheers

My Opera Community Enhancements

, ,

For those of you who still do not know "My Opera Community Enhancements" user script, I seriously recommend you give it a read. The script improves the user's experience here at my.opera. For a full feature list, just read the following documentation:
http://files.myopera.com/xErath/mopen/myopera-enhancements.html

The script was done mostly by me and BtEO, although BtEO will no longer participate in the script's development and maintenance.
Forum discussion at:
http://my.opera.com/community/forums/topic.dml?id=172834

Script contributions and bug reports are more than welcome.
Have fun, as always smile

Edit:
Whoops doh ! Forgot to post links...
Script: myopera-community-enhancements.js
External prefs file: myopera-community-enhancements-prefs.js