Getting the browser+platform keyboard modifiers
Asked Answered
M

3

7

I am creating a Web app that should be completely operated through the keyboard. I must provide the user the accesskey combination for different buttons, but the way accessing them is different for each browser and platform. E.g. For Chrome or Firefox in Ubuntu, if the accesskey is "d", I must press:

SHIFT+ALT+d

But if I access from Firefox 13 or older, I must use:

CTRL+d

So,the way to activate the accesskey depends on the browser and its platform.

I would like to know if there is a way to automatically detect which are those modifiers (SHIFT+ALT or CTRL) so I can properly update the instructions for the users according to their platform and browser.

TIA!

Maraud answered 9/7, 2020 at 0:46 Comment(1)
Even the documentation you linked recommends not using these.Flophouse
M
0

I ended up extending jquery and using platform.js:

(function ( $ ) {

    // Requires https://github.com/bestiejs/platform.js/blob/master/platform.js
    // Uses info https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey 

    class KMPlatform{
      constructor(p){this.platform = p}
        getAccessKeyActivators(){}
    }
    
    class KMLinux extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox')
            return ['alt','shift'];
        if(platform.name.startsWith('Opera'))
            return ['alt'];
        return [];
      }
    }
    
    class KMMac extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox' || platform.name.startsWith('Opera'))
            return ['ctrl','alt'];
        return [];
      }
    }
    
    class KMWindows extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox')
            return ['alt','shift'];
        if(platform.name == 'IE' || platform.name.startsWith('Opera'))
            return ['alt'];
        return [];
      }
    }

    $.extend({
       getAccessKeyActivators: function(){
           if(platform.os.family == 'Linux')
                return (new KMLinux(platform)).getAccessKeyActivators();
            else if (platform.os.family.startsWith('Mac'))
                return (new KMMac(platform)).getAccessKeyActivators();
            else if (platform.os.family.startsWith('Windows'))
                return (new KMWindows(platform)).getAccessKeyActivators();
            else return [];
       }
    });
}( jQuery ));

repo https://github.com/gbosetti/browser-access-keys-activators npm package https://www.npmjs.com/package/@gbosetti/access-keys-activators

Maraud answered 19/7, 2020 at 18:20 Comment(0)
F
2

Just use accessKeyLabel:

const btn = document.getElementById("btn"),
keyCombParagraph = document.getElementById("key-comb");

{
  const label = btn.accessKeyLabel;
  keyCombParagraph.innerHTML = label ?
    `This button can be activated by pressing ${label}.` :
    `This button doesn't have an assigned access key.`;
}

btn.addEventListener("click", () => {
  alert("Hello.");
});
<button id="btn" accesskey="h">Hello</button>
<p id="key-comb"></p>

Note that the spec does not define a format for accessKeyLabel and contains the following note:

Browsers on different platforms will show different labels, even for the same key combination, based on the convention prevalent on that platform. For example, if the key combination is the Control key, the Shift key, and the letter C, a Windows browser might display "Ctrl+Shift+C", whereas a Mac browser might display "^⇧C", while an Emacs browser might just display "C-C". Similarly, if the key combination is the Alt key and the Escape key, Windows might use "Alt+Esc", Mac might use "⌥⎋", and an Emacs browser might use "M-ESC" or "ESC ESC".

In general, therefore, it is unwise to attempt to parse the value returned from the accessKeyLabel IDL attribute.

Feingold answered 18/7, 2020 at 20:21 Comment(6)
Hi, thanks for the answer, but I know the accesskey. I mean, you can assign it like: <button accesskey="h" title="Caption" id="btn1">Hover me</button>. What I need is the modifiers label. E.g. Should I press CTRL+h or SHIFT+h?Maraud
That is what the snippet does.Feingold
Sorry, but the scrpt is returning the .accessKeyLabel, not the modifier keysMaraud
The .accessKeyLabel property contains the modifier keys in a human-readable representation. There is no way to get the modifiers without parsing it, which shouldn't be done.Feingold
I'm using Ubuntu 18 + Chrome and Firefox. Here is your script in a jsfiddle, which always returns: This button doesn't have an assigned access key. jsfiddle.net/gal007/u2rswty4/1Maraud
Oh, I thought it worked for you. It does for me on Windows. The spec says "The accessKeyLabel IDL attribute must return a string that represents the element's assigned access key, if any. If the element does not have one, then the IDL attribute must return the empty string.", so if it returns an empty string that means that the browser didn't assign a key combination (or that the browser doesn't support accessKeyLabel). In that case, the only way to "know" what the modifiers are is to use Dharman's answer.Feingold
U
0

You could simply detect browser and platform than using the table in link in your question to. This should give you access the info you are looking for.

Another option could be avoiding to use accesskey and using instead the altKey, ctrlKey and shiftKey properties of KeyboardEvents and build your own system.

Unaunabated answered 11/7, 2020 at 23:11 Comment(0)
M
0

I ended up extending jquery and using platform.js:

(function ( $ ) {

    // Requires https://github.com/bestiejs/platform.js/blob/master/platform.js
    // Uses info https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey 

    class KMPlatform{
      constructor(p){this.platform = p}
        getAccessKeyActivators(){}
    }
    
    class KMLinux extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox')
            return ['alt','shift'];
        if(platform.name.startsWith('Opera'))
            return ['alt'];
        return [];
      }
    }
    
    class KMMac extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox' || platform.name.startsWith('Opera'))
            return ['ctrl','alt'];
        return [];
      }
    }
    
    class KMWindows extends KMPlatform{
        getAccessKeyActivators(){
        if(platform.name == 'Chrome' || platform.name == 'Firefox')
            return ['alt','shift'];
        if(platform.name == 'IE' || platform.name.startsWith('Opera'))
            return ['alt'];
        return [];
      }
    }

    $.extend({
       getAccessKeyActivators: function(){
           if(platform.os.family == 'Linux')
                return (new KMLinux(platform)).getAccessKeyActivators();
            else if (platform.os.family.startsWith('Mac'))
                return (new KMMac(platform)).getAccessKeyActivators();
            else if (platform.os.family.startsWith('Windows'))
                return (new KMWindows(platform)).getAccessKeyActivators();
            else return [];
       }
    });
}( jQuery ));

repo https://github.com/gbosetti/browser-access-keys-activators npm package https://www.npmjs.com/package/@gbosetti/access-keys-activators

Maraud answered 19/7, 2020 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.