Extending Native Context Menus with HTML 5.1 <menu>

15th June 2017

One thing that annoys me when using the web is when some developer decided to do preventDefault() on contextmenu to replace the native context menu with some shitty app specific one, blocking my access to thing such as spellcheck, plugins, and search. It’s something I believe should be avoided whenever possible. Therefor I’m a fan of the possibility to extend the native one.

It should be noted that this is only available in Firefox for the moment.

My native context menu is full of useful features:


I added items to the context menu to my “bookshelf” now when right clicking a book you have the options to search after the book title at Amazon or Bokus.se as well as go back to byabbe.se.

Custom parts of the native context menu is defined using the <menu> element(<menu> is standardized to define menus for buttons and toolbar too), to link a <menu> to its container there is an contextmenu attribute, I added this attribute to the element containing all books as children.

<menu type="context" id="book-menu">
  <menuitem label="Go to byabbe.se" id="byabbe-se"></menuitem>
  <menu label="Search">
    <menuitem label="Bokus" id="bokus-search"></menuitem>
    <menuitem label="Amazon" id="amazon-search"></menuitem>

Adding actual functionality to the items is done with the regular click event. But in this case the action deepened upon which element(book) that the context menu had been triggered on. This was some thing I had too keep track of by another listener.

let currentContext = '';
document.querySelectorAll('.list')[0].addEventListener('contextmenu', e => {
  let target = e.target;
  let bookContainer;
  switch (e.target.tagName) {
    case 'SPAN':
      currentContext = target.parentElement.parentElement.children[0].innerText;
    case 'P':
      currentContext = target.parentElement.children[0].innerText;
    case 'B':
      currentContext = target.parentElement.children[0].innerText;
    case 'LI':
      currentContext = target.children[0].innerText;
      currentContext = target.innerText;

document.querySelector('#amazon-search').addEventListener('click', e => {
  document.location = 'https://www.amazon.com/s?field-keywords=' + currentContext;

document.querySelector('#bokus-search').addEventListener('click', e => {
  document.location = 'http://www.bokus.com/cgi-bin/product_search.cgi?search_word=' + currentContext;

You can try it out in Firefox over at byabbe.se/books/.


I believe there at least one major flaw with the <menu> element because you add items to the root of the menu, and there is no limit to the amount of items you can define. This results in tons of possible abuses such as using custom menu items to push the browser specific ones of screen(I tried, it works). It would be a lot better for the end user if all custom items would be one level below the root.

Playing with Service Workers

13th June 2017

I’m on a learning spree targeting web technologies, recently I played around with Service Workers adding functionality to some of my existing projects.

One of the projects I enchanted with offline support was my “bookshelf” a web app for browsing and searching the books I own. It’s a simple static site reading the contents from a single JSON file witch I update every now and then.

Two prerequisites that I had was:


Back an few years ago when AppCache was a new piece of the web, my and others approach to offline web apps was primarily simple, all files to be cached was defined in a manifest, all files only available over network and files for fallback was defined in the same file. When ever dynamic data was needed to be dealt with storing its content in LocalStorage or IndexedDB was an obvious approach. A update to the cache was triggered by changing something in the manifest(such as a comment).

# 0.0.1
# comment



It was possible to give a very basic site offline support in 30 seconds, but for anything with dynamic content you needed a strategy for storing and updating data.


Honestly I never got Opera to work with local development and Service Workers, I did a bunch of research into the topic of Chromium and the need of using localhost(not for development etc. Official examples could just do noting without any visible errors and I newer made sense of the random(at least for me random) network errors that sometimes showed up.

Switching to Firefox made everything work, out of the box, but it took me a while to do so.

My First Project

So going back to my bookshelf, my requirements for offline support was very basic, I wanted the cache to be automatically updated whenever network was available, I wanted all cache related code to be contained within the service worker, and not in the UI/main thread.

const CACHE_NAME = 'abbesbooks';

self.addEventListener('install', e => {
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll([

self.addEventListener('fetch', event => {

function loadFromCache(request) {
  return caches.open(CACHE_NAME).then(cache => {
    return cache.match(request).then(match => {
      return match || Promise.reject('failed-match');

function updateCache(request) {
  return caches.open(CACHE_NAME).then(cache => {
    return fetch(request).then(response => {
      return cache.put(request, response);

The Service Worker above is everything I did(except registering the Service Worker). At first I found thing like waitUntil() a bit weird but it made sense when I thought about JavaScript in general, although nothing like it seams to be required in Web Workers.

It should be noted that the example above is not a very useful example in most real world examples as it saves the user no data and displays old data until the page is refreshed once. It works for my needs but updateCache() could be limited to books.json and the view updated when fetched over the network.

AppCache gave us no control over the cache through JavaScript, Service Workers and the Cache API does just that and we can deal with dynamic contend without the need of other storage solutions.

I’m looking forward to play more with Service Workers especially in a non-cache context like load-balancing and Push notifications.

VirtualBox: Extending the Storage Size of a VM

2nd June 2017

I spend way to much time in a Virtual Machine, I always give them to little storage and I always find myself searching the web for a solution to increase the storage of a particular VM. This is my attempt to learn it for real once, or at least have all the information in the same place for future my needs.

Note: this solution only works for VDI/VHD files and before attempting this you should backup your VM.


The first of the tools to achieve larger storage is VBoxManage, you will find it in the root directory of your VirtualBox installation location.

Changing your VMs size to 80GB could be as simple as doing:

Did I say you should take a backup of your VM?

VBoxManage modifymedium /path/to/vm --resize 81920

If you are having a bad day and this just throws a error try replacing the path of the VM with its UUID. To list all your VMs and their UUIDs do:

VBoxManage list hdds

Now the VM got more logical storage assigned to it but this is usually not given to any existing partition. To resize your VM partitions you could use any of your favorite tools for the task.

I would suggest using GParted which is available on the installation ISO for Ubuntu. Just boot to it and select the “Try Ubuntu” option. Launching GParted is then as easy as $ gparted.

KSamsok-PHP 0.9

1st June 2017

I just took the time to release 0.9 of my KSamsok-PHP library and to update the documentation.

This release has breaking changes for those who extends the KSamsok class. This version brings increased speed and updated tests which are now connected to Travis. Also PHP type hints and modern array syntax is now in place.

Because of the major speed improvement this is a much recommended release. For those who are only using the existing methods and does not extend the core class no changes are needed. For everyone else, please note that the prepareUrl() and validResponse() methods has been removed. For more information see extending KSamsok-PHP and the breaking commit.

Older Newer