Заполнитель в contenteditable - фокусное событие - PullRequest
60 голосов
/ 01 февраля 2012

Я пытался спросить об этом раньше, без какой-либо удачи объяснить / доказать рабочий пример, где происходит ошибка. Итак, вот еще одна попытка:

Я пытаюсь воспроизвести эффект заполнителя для DIV. Основная концепция проста:

<div contenteditable><em>Edit me</em></div>

<script>
$('div').focus(function() {
    $(this).empty();
});
</script>

Это может иногда работать, но если заполнитель содержит HTML, или если выполняется какая-то другая обработка, текстовая вставка редактируемого DIV удаляется, и пользователь должен повторно щелкнуть редактируемый DIV, чтобы начать печатать ( даже если он все еще в фокусе):

Пример: http://jsfiddle.net/hHLXr/6/

Я не могу использовать триггер фокусировки в обработчике, так как он создаст цикл обработки событий. Поэтому мне нужен способ переустановить курсор каретки в редактируемом DIV или каким-либо другим способом перефокусировать.

Ответы [ 10 ]

153 голосов
/ 22 августа 2013

Вот решение только для CSS, дополняющее некоторые другие ответы: -

<div contentEditable=true data-ph="My Placeholder String"></div>
<style>
    [contentEditable=true]:empty:not(:focus)::before{
        content:attr(data-ph)
    }
</style>

РЕДАКТИРОВАТЬ: Вот мой фрагмент на codepen -> http://codepen.io/mrmoje/pen/lkLez

EDIT2: имейте в виду, что этот метод не работает на 100% для многострочных приложений из-за остаточных <br> элементов, присутствующих в div после выполнения select-all-cut или select-all-delete на всех строках. Кредиты: - @ vsync
Backspace вроде бы работает нормально (по крайней мере на webkit / blink)

28 голосов
/ 26 января 2013

Я только что опубликовал плагин для этого .

Он использует комбинацию CSS3 и JavaScript для отображения заполнителя без добавления к содержимому div:

HTML:

<div contenteditable='true' data-placeholder='Enter some text'></div>

CSS:

div[data-placeholder]:not(:focus):not([data-div-placeholder-content]):before {
    content: attr(data-placeholder);
    float: left;
    margin-left: 5px;
    color: gray;
}

JS:

(function ($) {
    $('div[data-placeholder]').on('keydown keypress input', function() {
        if (this.textContent) {
            this.dataset.divPlaceholderContent = 'true';
        }
        else {
            delete(this.dataset.divPlaceholderContent);
        }
    });
})(jQuery);

И это все.

24 голосов
/ 01 февраля 2012

Возможно, вам придется вручную обновить выбор. В IE событие focus слишком поздно, поэтому я бы предложил использовать событие activate. Вот некоторый код, который выполняет эту работу во всех основных браузерах, включая IE <= 8 (чего не будет с альтернативой только CSS): </p>

Демонстрация в реальном времени: http://jsfiddle.net/hHLXr/12/

Код:

$('div').on('activate', function() {
    $(this).empty();
    var range, sel;
    if ( (sel = document.selection) && document.body.createTextRange) {
        range = document.body.createTextRange();
        range.moveToElementText(this);
        range.select();
    }
});

$('div').focus(function() {
    if (this.hasChildNodes() && document.createRange && window.getSelection) {
        $(this).empty();
        var range = document.createRange();
        range.selectNodeContents(this);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    }
});
22 голосов
/ 10 января 2013

просто используйте псевдоклассы CSS.

span.spanclass:empty:before {content:"placeholder";}
8 голосов
/ 08 декабря 2013

Я обнаружил, что лучший способ сделать это - использовать атрибут placeholder, как обычно, и добавить несколько строк CSS.

HTML

<div contenteditable placeholder="I am a placeholder"></div>

CSS

[contenteditable][placeholder]:empty:before {
    content: attr(placeholder);
    color: #bababa;
}

Примечание: селектор CSS :empty работает только в том случае, если между открывающим и закрывающим тегом буквально ничего нет. Это включает в себя новые строки, вкладки, пустое место и т. Д.

Codepen

7 голосов
/ 12 декабря 2015

Все, что вам нужно, это маленькое решение

[contenteditable=true]:empty:before{
  content: attr(placeholder);
  display: block; /* For Firefox */
}

Демонстрация: http://codepen.io/flesler/pen/AEIFc

4 голосов
/ 24 августа 2013

Вот мой путь:

Он использует комбинацию jQuery и CSS3. Работает точно так же, как атрибут заполнителя html5! .

  • Прячется сразу при вводе первой буквы
  • Показывается снова, когда вы удаляете то, что вводите в него

HTML:

<div class="placeholder" contenteditable="true"></div>

CSS3:

.placeholder:after {
    content: "Your placeholder"; /* this is where you assign the place holder */
    position: absolute;
    top: 10px;
    color: #a9a9a9;
}

JQuery:

$('.placeholder').on('input', function(){
    if ($(this).text().length > 0) {
        $(this).removeClass('placeholder');
    } else {
        $(this).addClass('placeholder');
    }
});

ДЕМО: http://jsfiddle.net/Tomer123/D78X7/

1 голос
/ 16 апреля 2015

Вот исправление, которое я использовал.

<div contenteditable><em>Edit me</em></div>
<script>
$('div').focus(function() {
    var target = $(this);
    window.setTimeout(function() { target.empty(); }, 10);
});
</script>

Для этого я разработал плагин jQuery. Взгляните https://github.com/phitha/editableDiv

0 голосов
/ 10 июля 2017

Это не точное решение вашей проблемы ..

в наборе параметров summernote

airMode: правда

заполнитель работает таким образом.

0 голосов
/ 01 февраля 2012
var curText = 'Edit me';
$('div').focusin(function() {
    if ($(this).text().toLowerCase() == curText.toLowerCase() || !$(this).text().length) {
        $(this).empty();
    }
}).focusout(function() {
    if ($(this).text().toLowerCase() == curText.toLowerCase() || !$(this).text().length) {
        $(this).html('<em>' + curText + '</em>');
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...