contenteditable div 的占位符

Posted

技术标签:

【中文标题】contenteditable div 的占位符【英文标题】:Placeholder for contenteditable div 【发布时间】:2014-01-10 15:31:35 【问题描述】:

我有以下内容:FIDDLE

占位符可以正常工作,直到您键入内容、ctrl + Adelete。如果你这样做,占位符就会消失,并且再也不会出现。

怎么了?如何为可内容编辑的 div 设置占位符?

HTML:

<div class="test" placeholder="Type something..." contenteditable="true"></div>


CSS:
.test 
    width: 500px;
    height: 70px;
    background: #f5f5f5;
    border: 1px solid #ddd;
    padding: 5px;


.test[placeholder]:empty:before 
    content: attr(placeholder);
    color: #555; 


谢谢。

【问题讨论】:

你用的是什么浏览器?我不能 ctrl+a .. 也不能删除占位符文本。 它在 Chrome 上运行良好,您使用的是哪个浏览器? 在 FF 上也能正常工作 我正在使用 Firefox,但它无法正常工作(是的,我有最新的更新)。 :// 不知道 CSS attr() - 谢谢! 【参考方案1】:

我明白你的意思。在你的小提琴中,我输入了几个字符并使用'ctrl-a'和'delete'将其删除,占位符重新出现。

但是,似乎当您在 contenteditabele div 中点击“输入”时,它会创建一个包含换行符 &lt;div&gt;&lt;br&gt;&lt;/div&gt; 的子 div,这会导致 :empty 伪类出现问题,该伪类仅针对没有子元素。**

在 chrome 开发人员工具或您使用的任何工具中查看。

来自 developer.mozilla.org

:empty 伪类表示任何没有子元素的元素。仅考虑元素节点和文本(包括空格)。注释或处理指令不会影响元素是否被视为空。

Ctrl-a 将删除文本,但保留子 div。或许可以通过添加一些 javascript 来解决这个问题。

【讨论】:

好地方 - &lt;div&gt;&lt;br&gt;&lt;/div&gt; :)【参考方案2】:

正如斯威夫特所说,你可以用一些超级简单的 JS 来解决这个问题。使用 jQuery:

var $input = $(".test");
$input.keyup(function () 
    if ($input.text().length == 0) 
        $input.empty();
    
);

在每次击键时,它都会检查是否存在任何输入文本。如果不是,它会破坏用户与元素交互可能留下的任何子元素——例如&lt;div&gt; 斯威夫特描述。

【讨论】:

+1 不错,但在更多情况下可能会发生这种情况(右键单击 + 剪切)。【参考方案3】:

更新 Christian Brink 的答案,您可以/应该检查更多事件。你可以这样做:

// More descriptive name
var $input = $(".placeholder");
function clearPlaceHolder() 
  if ($input.text().length == 0) 
    $input.empty();
    
  

// On each click
$input.keyup(clearPlaceHolder);

// Probably not needed, but just in case
$input.click(clearPlaceHolder);

// Copy/paste/cut events http://***.com/q/17796731
$input.bind('input', (clearPlaceHolder));

// Other strange events (javascript modification of value?)
$input.change(clearPlaceHolder);

最后,updated JSFiddle

【讨论】:

谢谢弗朗西斯科,比我的更全面,也很清晰。【参考方案4】:

我有这个功能,而且我总是用来防止这种事情发生。

我是这样使用我的函数的:

var notEmpty = 

    notEmpty.selector = ".no-empty-plz"
    notEmpty.event = "focusout"
    notEmpty.nonEmpty = "---"


    neverEmpty(notEmpty)

我只是将 no-empty-plz 添加到我不想为空的元素中。

/**
     * Used to prevent a element have a empty content, made to be used 
when we want to edit the content directly with the contenteditable=true 
because when a element is completely empty, it disappears U_U
     * 
     * @param selector
     * @param event
     * @param nonEmpty:
     *        String to be put instead empty
     */
function neverEmpty(params) 

    var element = $(params.selector)



    $(document).on(params.event, params.selector, function() 

        var text = $(this).html()
        text = hardTrim(text)

        if ($.trim(text)  == "") 
            $(this).html(params.nonEmpty)
        
    );

params其实是一个json,所以你可以看到selector = params.selector

hardTrim 也是我创建的另一个 fucntion,类似于修剪,但包括 &nbsp 和 &lt;br/&gt;,

function hardTrim(text) 

    if (!exists(text)) 
        return ""
    
    text = text.replace(/^\&nbsp\;|<br?\>*/gi, "").replace(/\&nbsp\;|<br?\>$/gi, "").trim();

    return text

【讨论】:

【参考方案5】:

在寻找同样的问题时,我想出了一个简单的混合 css-JavaScript 解决方案,我想分享一下:

CSS:

[placeholder]:empty::before 
    content: attr(placeholder);
    color: #555; 


[placeholder]:empty:focus::before 
    content: "";

JavaScript:

jQuery(function($)
    $("[contenteditable]").focusout(function()
        var element = $(this);        
        if (!element.text().trim().length) 
            element.empty();
        
    );
);

Updated fiddle

【讨论】:

我的页面加载时如何获取占位符?它工作得很好,但是在我输入了一些内容并删除了输入字段中的所有内容之后它就开始了。 也许你的元素不是空的?上面的代码只过滤空格,而不是换行符。 占位符应该保留,除非您输入内容。这消失了。 对于您的假设行为,只需从 css 中删除 [placeholder]:empty:focus:before 元素。 请加cursor: text;,否则显示占位符时光标会变成箭头【参考方案6】:

感觉就像我在重复自己,但为什么不检查contenteditable 元素突变呢?试图将所有内容绑定到正在更改内容的事件是一件很痛苦的事情。如果您需要添加按钮(例如粘贴)或动态更改内容(javascript)怎么办。我的方法是使用MutationObservers。演示fiddle

HTML:

<div class="test" id="test" placeholder="Type something..." contenteditable="true"></div>

CSS:

.test 
    width: 500px;
    height: 70px;
    background: #f5f5f5;
    border: 1px solid #ddd;
    padding: 5px;


.test[placeholder]:empty:before 
    content: attr(placeholder);
    color: #555; 

JavaScript:

var target = document.querySelector('#test');
var observer = new MutationObserver(function(mutations) 
  mutations.forEach(function(mutation) 
      if (target.textContent == '') 
          target.innerHTML = '';
      
  );    
);
var config =  attributes: true, childList: true, characterData: true ;
observer.observe(target, config);

【讨论】:

【参考方案7】:

一些修复:

1) $element.text().trim().length - 它解决了 &lt;div&gt;&lt;br/&gt;&lt;/div&gt;&amp;nbsp; 的问题

2) data-placeholder attr 而不是 placeholder - 这是正确的方式

3) 普通选择器$("[contenteditable]") - 是真的方式

4) display: inline-block; - 修复 Chrome 和 Firefox

JavaScript:

jQuery(function($)
    $("[contenteditable]").blur(function()
        var $element = $(this);
        if ($element.html().length && !$element.text().trim().length) 
            $element.empty();
        
    );
);

HTML:

<div data-placeholder="Type something..." contenteditable="true"></div>

CSS:

[contenteditable]:empty:before 
    content: attr(data-placeholder);
    color: grey;
    display: inline-block;

【讨论】:

这个解决方案删除了​​  在 div 中如果你需要  在里面【参考方案8】:

来自Placeholder in contenteditable - focus event issue

[contenteditable=true]:empty:not(:focus):before
  content:attr(data-ph);
  color:grey;
  font-style:italic;

【讨论】:

当 div contenteditable 为空并且我加载页面时,它不会显示任何内容。占位符在我输入后才起作用,然后我用退格键清除 div contenteditable。如果一开始就想要怎么办 基于 CSS 的最佳解决方案。【参考方案9】:

我创建了一个现场演示:“内容可编辑 div 的占位符”,由 HTML 和 CSS 编写。 另外,Codepen:https://codepen.io/fritx/pen/NZpbqW 参考:https://github.com/fritx/vue-at/issues/39#issuecomment-504412421

.editor 
  border: solid 1px gray;
  width: 300px;
  height: 100px;
  padding: 6px;
  overflow: scroll;

[contenteditable][placeholder]:empty:before 
  content: attr(placeholder);
  position: absolute;
  color: gray;
  background-color: transparent;
<textarea class="editor"
  placeholder="Textarea placeholder..."
></textarea>
<br/>
<br/>
<div class="editor"
  contenteditable
  placeholder="Div placeholder..."
  oninput="if(this.innerHTML.trim()==='<br>')this.innerHTML=''"
></div>

【讨论】:

【参考方案10】:

我的解决方案来自:https://codepen.io/flesler/pen/AEIFc

基本上放这个css代码:

[contenteditable=true]:empty:before
  content: attr(placeholder);
  pointer-events: none;
  display: block; /* For Firefox */

并且在你的 contenteditable div 中有 placeholder 属性。

【讨论】:

这很漂亮 这非常酷,适合许多用例,谢谢! 这是完美的,为什么这不是更高的! 答案不错,但并不完美。必须有 javascript 来清除为 contenteditable div 中的新行创建的 break 标记和 div 标记。为了证明这一点,请在可编辑的 div 中输入一些内容,然后单击 enter 以创建新行。然后按 control+A 选择所有文本并用退格键删除。结果??没有占位符了【参考方案11】:

这个解决方案对我有用。我已将此解决方案从 angular 转换为纯 javaScript

在.html中

<div placeholder="Write your message.." id="MyConteditableElement" onclick="clickedOnInput = true;" contenteditable class="form-control edit-box"></div>

在.css中

.holder:before 
    content: attr(placeholder);
    color: lightgray;
    display: block;
    position:absolute;    
    font-family: "Campton", sans-serif;

在js中。

clickedOnInput:boolean = false;
charactorCount:number = 0;
let charCount = document.getElementsByClassName('edit-box')[0];

if(charCount)
this.charactorCount = charCount.innerText.length;


if(charactorCount > 0 && clickedOnInput)
document.getElementById("MyConteditableElement").classList.add('holder');


if(charactorCount == 0 && !clickedOnInput)
document.getElementById("MyConteditableElement").classList.remove('holder');


getContent(innerText)
  this.clickedOnInput = false;

【讨论】:

以上是关于contenteditable div 的占位符的主要内容,如果未能解决你的问题,请参考以下文章

css CSS - 对contentEditable元素的占位符支持

如何将光标位置放在 contenteditable 元素的居中对齐占位符的开头?

text 添加占位符,在-DIV标签

如果已经在 contenteditable 上打字,则禁用打字机功能

类似于Trello的Javascript拖放悬停临时Div占位符?

在 Angular 中使用占位符