点击外面一个contenteditable div静止关注它吗? [英] Clicking outside a contenteditable div stills give focus to it?

查看:122
本文介绍了点击外面一个contenteditable div静止关注它吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于某种原因,我需要使用contenteditable div而不是普通的文本输入来输入文本。 (对于一些javascript库)它工作正常,直到我发现,当我设置contenteditable div使用 display:inline-block ,它给予重点的div,即使我点击外面div!



我需要它把重点放在div只有当用户点击到div,但不是在它周围。目前,我发现当用户点击其他地方,然后点击与div相同行的位置时,它会聚焦它。



一个简单的示例问题:



HTML:

 < div class =外部> 
< div class =text-inputcontenteditable =true>
输入1
< / div>
< div class =text-inputcontenteditable =true>
输入2
< / div>
< div class =unrelated>这是一些不相关的内容< br>
这是一些更不相关的内容
这只是一些空间,显示点击这里不会与contenteditable div
混淆,但点击边乱。
< / div>
< / div>

CSS:

 code> div.outside {
margin:30px;
}
div.text-input {
display:inline-block;
background-color:black;
color:white;
width:300px;
}

用于显示问题的JSFiddle



有一种方法(CSS或javascript都是可接受的),使浏览器只将重点放在div它是单击而不是点击相同的行?



PS我注意到有类似的问题(链接到其他相关的帖子),但是情况有点不同,提供的解决方案对我来说不起作用。

解决方案

说明(如果您不在乎,请跳至下面的解决方法部分)



当您点击可编辑元素时,浏览器会将光标插入点)在最近的文本节点,它与您的点击在同一行上 - 即使该节点位于您点击的元素的子元素中。您可以通过点击下面的代码段验证这一点。



  .container {width:auto; padding:30px; background:tan;}。container * {margin:4px; padding:4px;} div {width:50%; background:lightgreen;} span {background:orange;} span> span {background:gold;} span> span> span {background:yellow;}  

 < div class = containercontenteditable> text< div> div中的文字< / div> &span;< / span>< / span>< / span>< / div>请注意,您可以通过点击第一行或以下最后。一些其他答案不解释这一点! 



大棕褐色框是一个可编辑元素,内部彩色框是嵌套的子元素。请注意,如果单击子元素旁边,则光标将位于其内部,即使您单击外部。这种行为没有什么奇怪的;

奇怪的是,在Webkit浏览器(Chrome,Safari,Opera)中,这不是所有浏览器的可编辑性确定是否获得闪烁的光标的点击元素 - 它是最近的文本节点(可能在子元素中,如上所示)的可编辑性。换句话说,他们这样做:

 点击:
找到最近的文本节点;
如果文本节点是可编辑的:
添加插入点;

...当他们应该这样做:

 点击:
如果点击的元素是可编辑的:
查找最近的文本节点;
添加插入点;

我认为这是一个错误。



阻止元素(例如div)似乎不受该错误的影响,这让我认为 @GOTO 0的回答在涉及文本选择时是正确的 - 至少在它似乎受控制插入点放置的相同逻辑控制的范围内。通常,您可以通过在元素外部多次点击来选择元素中的文本,但如果元素恰好是块,则它不会工作。外部点击也不会在块中触发插入点布置,这可能不是巧合。下面的第一个解决方法是利用此行为。






解决方法1 b
$ b

由于块不受错误影响,我认为最好的解决方案是在inline-block中嵌入一个div,并使其可编辑。内联块在内部已经表现得像块一样,所以div不应该影响其行为。



  div.outside {margin:30px;} div.text-input {display:inline-block;背景颜色:黑色;颜色:白色; width:300px;}  

 < div class = > < div class =text-input> < div contenteditable>输入1< / div> < / div> < div class =text-input> < div contenteditable>输入2< / div> < / div> < div class =unrelated>这是一些不相关的内容< br>这是一些更不相关的内容这只是一些空间,显示,点击这里不会与可编辑的div,但点击边混乱与它。 < / div>< / div>  






解决方法2



如果必须将 contenteditable 属性在inline-blocks,这个解决方案将允许它。它通过使用不可见字符(具体来说,零宽度空格)来围绕每个可编辑块,从而屏蔽其免受外部点击。 ( GOTO 0的回答使用相同的原则,但在我检查后仍然有一些问题)。



  div.outside {margin:30px;} div.text-input {display:inline-block;背景颜色:黑色;颜色:白色; width:300px; white-space:normal;}。input-container {white-space:nowrap;}  

 < div class =outside> < span class =input-container>&#8203;< div class =text-inputcontenteditable>输入1< / div>&#8203;< / span> < span class =input-container>&#8203;< div class =text-inputcontenteditable>输入2< / div>&#8203;< / span> < div class =unrelated>这是一些不相关的内容< br>这是一些更不相关的内容这只是一些空间,显示,点击这里不会与可编辑的div,但点击边混乱与它。 < / div>< / div>  






解决方法3



如果您绝对无法更改标记,作为最后手段(受此答案启发)。它会在内联块被点击时将 contentEditable 设置为true,而当它们失去焦点时将其设置为false。



 (function(){var inputs = document.querySelectorAll('。text-input'); for(var i = inputs.length; ;} {inputs [i] .addEventListener('click',function(e){e.target.contentEditable = true; e.target.focus();}); inputs [i] .addEventListener (e){e.target.contentEditable = false;});}})();  

  div.outside {margin:30px;} div.text-input {display:inline-block;背景颜色:黑色;颜色:白色; width:300px;}  

 < div class = > < div class =text-input>输入1< / div> < div class =text-input>输入2< / div> < div class =unrelated>这是一些不相关的内容< br>这是一些更不相关的内容这只是一些空间,显示,点击这里不会与可编辑的div,但点击边混乱与它。 < / div>< / div>  


For some reason I need to use contenteditable div instead of normal text input for inputting text. (for some javascript library) It works fine until I found that when I set the contenteditable div using display: inline-block, it gives focus to the div even if I click outside the div!

I need it to be giving focus to the div only when the user clicks right onto the div but not around it. Currently, I found that when the user clicks elsewhere and then click at position that is the same row as the div, it gives focus to it.

A simple example to show the problem:

HTML:

<div class="outside">
    <div class="text-input" contenteditable="true">
        Input 1
    </div>
    <div class="text-input" contenteditable="true">
        Input 2
    </div>
    <div class="unrelated">This is some unrelated content<br>
      This is some more unrelated content
      This is just some space to shows that clicking here doesn't mess with the contenteditable div
      but clicking the side mess with it.
    </div>
</div>

CSS:

div.outside {
  margin: 30px;
}
div.text-input {
  display:inline-block;
  background-color: black;
  color: white;
  width: 300px;
}

The JSFiddle for displaying the problem

Is there a way (CSS or javascript are both acceptable) to make the browser only give focus to div when it is clicked instead of clicking the same row?

P.S. I noticed that there are similar problem (link to other related post), but the situation is a bit different and the solution provided is not working for me.

解决方案

Explanation (if you don't care, skip to the Workarounds section below)

When you click in an editable element, the browser places a cursor (a.k.a. insertion point) in the nearest text node that's on the same line as your click-- even if that node is in a child of the element you clicked on. You can verify this by clicking around in the code snippet below.

.container {width: auto; padding: 30px; background: tan;}
.container * {margin: 4px; padding: 4px;}
div {width: 50%; background: lightgreen;}
span {background: orange;}
span > span {background: gold;}
span > span > span {background: yellow;}

<div class="container" contenteditable>
  text
  <div>
    text in a div
  </div>
  <span><span><span>text in spans</span></span></span></div>
Notice that you can get an insertion point by clicking above the first line or below the last. Some of the other answers don't account for this!

The large tan box is an editable element and the inner colored boxes are nested child elements. Notice that if you click beside a child element, the cursor ends up inside it, even though you clicked outside. There's nothing strange about this behavior; it's common to all browsers.

What is strange is that, in Webkit browsers (Chrome, Safari, Opera), it's not the editability of the clicked element that determines whether you get a blinking cursor or not-- it's the editability of the nearest text node (which may be in a child element, as demonstrated above). In other words, they're doing this:

on click:
  find nearest text node;
  if text node is editable:
    add insertion point;

...when they should be doing this:

on click:
  if clicked element is editable:
    find nearest text node;
    add insertion point;

I'd consider that a bug.

Block elements (such as divs) don't seem to be affected by the bug, which makes me think @GOTO 0's answer is correct in implicating text selection-- at least insofar as it seems to be governed by the same logic that controls insertion point placement. Normally, you can select the text within an element by multi-clicking outside the element, but it doesn't work if the element happens to be a block. It's probably no coincidence that external clicks also don't trigger insertion point placement in a block. The first workaround below makes use of this behavior.


Workaround 1

Since blocks aren't affected by the bug, I think the best solution is to nest a div in the inline-block and make it editable instead. Inline-blocks already behave like blocks internally, so the div should have no effect on its behavior.

div.outside {
  margin: 30px;
}
div.text-input {
  display:inline-block;
  background-color: black;
  color: white;
  width: 300px;
}

<div class="outside">
    <div class="text-input">
      <div contenteditable>
        Input 1
      </div>
    </div>
    <div class="text-input">
      <div contenteditable>
        Input 2
      </div>
    </div>
    <div class="unrelated">This is some unrelated content<br>
      This is some more unrelated content
      This is just some space to shows that clicking here doesn't mess with the contenteditable div
      but clicking the side mess with it.
    </div>
</div>


Workaround 2

If you must put the contenteditable attribute on the inline-blocks, this solution will allow it. It works by surrounding each editable block with invisible characters (specifically, zero-width spaces) which shield it from external clicks. (GOTO 0's answer uses the same principle, but it still had some problems last I checked).

div.outside {
  margin: 30px;
}
div.text-input {
  display:inline-block;
  background-color: black;
  color: white;
  width: 300px;
  white-space: normal;
}
.input-container {white-space: nowrap;}

<div class="outside">
  <span class="input-container">&#8203;<div class="text-input" contenteditable>
    Input 1
  </div>&#8203;</span>
  <span class="input-container">&#8203;<div class="text-input" contenteditable>
    Input 2
  </div>&#8203;</span>
  <div class="unrelated">This is some unrelated content<br>
      This is some more unrelated content
      This is just some space to shows that clicking here doesn't mess with the contenteditable div
      but clicking the side mess with it.
  </div>
</div>


Workaround 3

If you absolutely can't change your markup, then this JavaScript-based solution could work as a last resort (inspired by this answer). It sets contentEditable to true when the inline-blocks are clicked, and false when they lose focus.

(function() {
  var inputs = document.querySelectorAll('.text-input');
  for(var i = inputs.length; i--;) {
    inputs[i].addEventListener('click', function(e) {
      e.target.contentEditable = true;
      e.target.focus();
    });
    inputs[i].addEventListener('blur', function(e) {
      e.target.contentEditable = false;
    });
  }
})();

div.outside {
  margin: 30px;
}
div.text-input {
  display:inline-block;
  background-color: black;
  color: white;
  width: 300px;
}

<div class="outside">
    <div class="text-input">
      Input 1
    </div>
    <div class="text-input">
      Input 2
    </div>
    <div class="unrelated">This is some unrelated content<br>
      This is some more unrelated content
      This is just some space to shows that clicking here doesn't mess with the contenteditable div
      but clicking the side mess with it.
    </div>
</div>

这篇关于点击外面一个contenteditable div静止关注它吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆