17

I'm trying to listen to focus / blur events on span with contenteditable=true attribute.

So here's what I tried (jQuery) :

$('.editable').on('focus',function(){
    var that = $(this),
        defaultTxt = that.data('default');
    that.html('');
});
$('.editable').on('blur',function(){
    var that = $(this),
        defaultTxt = that.data('default');
    if(that.html() === ''){
        that.html(defaultTxt);
    }
});

But he doesn't seem to work, because span doesn't handle focus / blur. How can I achieve that anyway (IE8 support needed) ?

enguerranws
  • 8,087
  • 8
  • 49
  • 97

2 Answers2

30

There are two ways to achieve this effect.

Approach 1: focusin and focusout

$('.editable').on('focusin', function() {
    // your code here
});

$('.editable').on('focusout', function() {
    // your code here
});

focusin and focusout are like focus and blur events, but unlike the latter, they are fired on almost(?) every element, and also bubble. focusin and focusout are a part of DOM level 3 Specification. Firefox 51 and older didn't support this due to a known bug, but Firefox 52 and above have full support.

Approach 2: click and focus

This only works if you have other focusable elements around your span. What you do is basically use the focus event on any other element as a blur handler.

$('.editable').on('click', function() {
    // your code here
});

$('*').on('focus', function() {
    // handle blur here
    // your code here
});

I wouldn't recommend this approach in a large webapp, because browser performance will take a hit.

turtleDev
  • 416
  • 4
  • 3
  • Mozilla implemented a fix for OP's linked bug in Firefox 52. Majority of Firefox users are on v52 or later, but there are still users on older versions (https://caniuse.com/usage-table). – CFitz Jun 12 '18 at 15:40
3

I have created a demo for you:

$('.editable').bind('click', function(){
  $(this).attr('contentEditable',true);
});

$('.editable').bind('focus', function() {
  var that = $(this);
  //defaultTxt = that.data('default');
  that.html('');    
});

$('.editable').bind('blur', function() {
  var that = $(this);
  var defaultTxt = that.data('default');
  if(that.html() === ''){
    that.html(defaultTxt);
  }    
});
.editable{
    padding: 5px;
    border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<span class="editable" data-default="default">Some text</span>

I have changed your code, take a look it. Also now it's keeping the old value when lost the focus if you don't type anything.

gon250
  • 3,405
  • 6
  • 44
  • 75
  • 1
    As you can see, it doesn't work properly : the first click on the span just add the contenteditable attribute (note : it's already set in the HTML), only the second one focus on the span. Thank you anyway for that. – enguerranws Apr 13 '15 at 07:16