9

After a great answer I see this might be a possible duplicate of Placeholder in contenteditable - focus event issue

I have an HTML <span> element with the contenteditable="true". My goal is to have a seamless 'input' field utilizing the span element. I'm having issues getting the following flow to work:

  • The DOM loads with <span> editable and default text of 'Make a new tag ..'
  • When User clicks on the <span> the text updates to say 'Begin typing ..'
  • On first keypress, remove <span> text and begin filling with User input
  • If the <span> has no text and the user is still editing, replace text with 'Begin typing ..'
  • If the <span> has no text and the user is not interacting, replace text with 'Make a new tag ..'

It works except that when the User is editing the element and they clear all text, the element collapses and becomes uneditable. I need to make sure there is always text inside the <span> or I need to find another method of handling these cases

Here is the element I am working with:
*Note: I am using jQuery, Bootstrap, and FontAwesome

<span class="badge"><span contenteditable="true" id="new-tag" class="badge alert-info">Make a new tag ..</span><i class="fa fa-lg fa-plus-circle"></i></span>  

And my javascript:

$('#new-tag').click(function(){
    if( $(this).data('editing') !== 'active'){
        $(this).text('Start typing ..');
    }
});

// i do it this way because when .text('') is used, the <span> breaks
$('#new-tag').keydown(function(e){
    if( $(this).data('editing') !== 'active'){
        $(this).text(String.fromCharCode(e.charCode));
    }
    $(this).data('editing','active');
});

$('#new-tag').change(function(){
    if( $(this).data('editing') == 'active' && $(this).text() == ''){
        $(this).text('Make a new tag ..');
        $(this).removeData('editing');
    }
});

Can someone make this magic happen? Here is a fiddle of what I have posted.

Community
  • 1
  • 1
Qwiso
  • 135
  • 2
  • 3
  • 9

2 Answers2

25

I'd suggest that you could consider using CSS:

span.badge[contenteditable] {
    display: inline-block;
}
span.badge[contenteditable]:empty::before {
    content: 'Make a new tag';
    display: inline-block;
}
span.badge[contenteditable]:empty:focus::before {
    content: 'Start typing';
}

JS Fiddle demo.

And to make it more customisable, given the data-* attributes in the HTML:

<span class="badge">
    <span contenteditable="true" id="new-tag" class="badge alert-info" data-placeholder="Make a new tag" data-focused-advice="Start typing"></span><i class="fa fa-lg fa-plus-circle"></i>
</span>

The following CSS will use those custom attributes to place the appropriate text:

span.badge[contenteditable] {
    display: inline-block;
}
span.badge[contenteditable]:empty::before {
    content: attr(data-placeholder);
    display: inline-block;
}
span.badge[contenteditable]:empty:focus::before {
    content: attr(data-focused-advice);
}

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • 1
    Very clean solution! Wow – Qwiso Nov 16 '14 at 18:33
  • Nevermind, I'm dumb and didn't update the element. Only the CSS. Your answer is flawless. Hah – Qwiso Nov 16 '14 at 19:05
  • 1
    Right. The selector for the 'Start typing..' includes the selector `:empty`. This selector requires that there *be no elements, text or white-space*. Therefore it can't match, since you (for some reason) seem to have hard-coded the 'Make a new tag' text in the HTML. You can either remove the `:empty` selector from the CSS, or you can use the approach I showed in my answer that doesn't require, or want, any content in the `[contenteditable]` span. – David Thomas Nov 16 '14 at 19:09
  • Works like a charm! I just changed the color of the text of the two `::before` to emulate the normal placeholder. – Marco Bernardini Apr 14 '15 at 09:32
2

http://jsfiddle.net/rwmoehsc/2/

Add this css:

#new-tag {
   min-width: 150px;
   display: block;
   min-height: 20px;
}

Edit: I do not lose the ability to edit the element in FF 33

Edit 2: Nor in chrome 38

C Bauer
  • 5,003
  • 4
  • 33
  • 62
  • If you edit the element and press ctrl+a and backspace to clear everything, in chrome, it collapses and becomes inactive. Does the same happen to you? – Qwiso Nov 16 '14 at 18:28
  • Oh, interesting. Yes, I was just clicking it and typing, which doesn't cause this behavior. – C Bauer Nov 16 '14 at 18:29