Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I detect support for contentEditable via JavaScript?

I've been searching for this for a couple of days now and so far, the best I can come up with is checking the list below. I really don't like to check for support based on User-Agent, especially since it can be spoofed. I've also heard of at least one instance where the list below is incorrect (noted below).

  • Is Internet Explorer?
  • Is WebKit? (But I've read that mobile Safari doesn't support it)
  • Is Opera?
  • Is Gecko and version >= 1.9? (meaning Firefox 3 or later)

Is there a better method based on testing for support directly via JavaScript, or is this pretty much the only way to test for support?

like image 586
Jason Avatar asked Dec 10 '09 16:12

Jason


4 Answers

var canEditContent= 'contentEditable' in document.body;
like image 183
bobince Avatar answered Nov 13 '22 02:11

bobince


The best way to check for a certain feature is to actually test for that feature on an element that you know should support it, like this:

if(element.contentEditable != null)
    // then it's supported

or

if(typeof(element.contentEditable) != 'undefined')
   // same thing.. but with typeof you can be more specific about the type of property you need to find
like image 43
Mike Dinescu Avatar answered Nov 13 '22 01:11

Mike Dinescu


The best solution for my scenario (similar to yours) I came up with is below. It's not probably bulletproof, but covers most of the situations:

var ua = navigator.userAgent;
var android_version = ua.match(/Android ([0-9\.]+)/);
var div = document.createElement("DIV");

if( typeof(div.contentEditable) == 'undefined' ||
  (/(iPhone|iPod|iPad)/i.test(ua) && /OS [1-4]_\d like Mac OS X/i.test(ua)) ||
  (android_version!=null && parseFloat(android_version[1])<3 ) ||
  (/(Opera Mobi)/i.test(ua))
) {
  // doesn't support contenteditable
} else {
  // supports contenteditable
}

You can test it out in this jsFiddle.

Notice: Depending on your needs and purpose, you might need to detect IE version as well, because it's support of contenteditable is ... "not ideal" :-) Most of the pains is dealt by super library Rangy.js.

like image 2
Frodik Avatar answered Nov 13 '22 02:11

Frodik


bobince's answer works for the most part but, as has been said, you will need user agent sniffing to exclude iOS and Android versions that don't bring up the software keyboard. I'm currently using something like this:

function isContentEditable() {
    var canEditContent = 'contentEditable' in document.body;
    if (canEditContent) {
        var webkit = navigator.userAgent.match(/(?:iPad|iPhone|Android).* AppleWebKit\/([^ ]+)/);
        if (webkit && parseInt(webkit[1]) < 534) {
            return false;
        }
    }
    return canEditContent;
}

This should stop older iOS and Android devices from returning true. It still has one problem though: physical keyboards. If, for example, a device is running Android 2.3 but has a physical keyboard then the user will be able to use contentEditable but this function will return false. Physical keyboards are quite rare though.

More commonly, on some devices it may be possible for the user to bring up the on screen keyboard by pressing and holding the menu button. Obviously this isn't really something you should expect your users to know about.

You could mitigate these issues slightly by having some way for the user to manually override the sniffing part of the detection script. You could implement this in the isContentEditable function by adding an override check to "if (canEditContent)". However, Implementing the UI for this might present more of a challenge ;).

like image 1
ChrisD Avatar answered Nov 13 '22 03:11

ChrisD