HTML,CSS,JS - 具有永久领先内容的Contenteditable div [英] HTML, CSS, JS - Contenteditable div with permanent leading content

查看:159
本文介绍了HTML,CSS,JS - 具有永久领先内容的Contenteditable div的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 contenteditable div,例如:

  ; div id =textcontenteditable =true>< / div> 

我想要的是将另一个div(或span,不可编辑) #text ,其中用户不能在其之前插入文本,或者甚至将光标移动到它之前。



尝试了以下变体:

 < div id =textcontenteditable =true> 
< span class =leadcontenteditable =false>这是一些领导< / span>
< / div>

您可以看到此设置的正在运行的版本





想法?任何事情,让我在正确的方向是欢迎!

解决方案

解决方案



a href =https://jsfiddle.net/9ntud4yx/31/ =nofollow> Tada!< - 链接到小提琴(如果太细微)





首先,让我们感谢此讯息这篇文章,让我们走在正确的轨道上。



现在,它是如何工作的:





 < div id =testingcontenteditable = true>< span contenteditable =falseclass =lead>有什么东西< / span>&#8203;< / div& 

注意!如果你想删除前面的< span> ,你必须把一切都放在一行。



这个东西没什么特别的,可以工作与否。只是我如何设置它,暂时。

  #testing {
padding:5px;
width:90%;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box;
font-size:13px;
color:#3B3B3B;
margin:0px 0px 15px 0px;
resize:none;
overflow:hidden;
background-color:#FAFAFA;
line-height:15px;
min-height:42px;
max-height:160px;
outline:none;
}
.lead {
color:#000;
background:#ccd;
padding:1px 2px 1px 2px;
font-size:12px;
margin-right:4px;
border:none;
-webkit-touch-callout:none; / * iOS Safari * /
-webkit-user-select:none; / * Chrome / Safari / Opera * /
-khtml-user-select:none; / * Konqueror * /
-moz-user-select:none; / * Firefox * /
-ms-user-select:none; / * Internet Explorer / Edge * /
用户选择:无;
}

JS / p>

这是肉类和土豆的整个事情!我不会覆盖我提到的两个来源的代码片段,所以自己来处理。



变量

  var somethingVisible = true; 
var somethingsomething ='< span contenteditable =falseclass =lead>某事< / span>&#8203;';
var spanContLen = $('。lead')。html()。length + 1;

somethingVisible sV ,从而)跟踪< span> 元素是否是 contenteditable div。



somethingsomething ss



spanContLen>

scl ,以下)是< span> 元素,加1为空白字符。这用于比较光标/插入符号的位置。



然后其余...

  $('#testing')。on('keydown',function(e){
if(somethingVisible){
var pos = getCaretPosition(this);
if(pos< spanContLen){
setPos(this);
}

if(pos< = spanContLen& e.keyCode == 8 ){
$('。lead')。remove();
somethingVisible = false;
}
}
})on('keyup' (e){
if(somethingVisible){
var pos = getCaretPosition(this);
if(pos< spanContLen){
setPos(this);
}
}
})on('click',function(e){
if(somethingVisible){
var pos = getCaretPosition(this);
if (pos< spanContLen){
setPos(this);
}
}
});

不要太糟糕,噢!?



基本上,它的工作原理如下:




  • 如果用户在小于 sol ,将光标移动到< span> 后的第一个位置。 $ c> keydown 在防止用户成为忍者时特别出色,他们像上箭头那样几乎按几个字符键(这具有放置在光标已被编程移回之前的< span> 前的字符)

  • 如果光标位于 scl position,并且用户按 backspace 键( keyCode == 8 ),然后删除< span> 元素,并将 sV 设置为false。



这不是完美的,我敢肯定,但它的工作原理我想要的。一个用户可能是一个巨大的,空隙的屁股,并禁用他们的JS来绕过系统。



在上面链接的小提琴中,添加(Add)按钮可以帮助您确保您的用户不会损坏您的内容。如果您选择删除股票,则后退按钮只是插入新的< span> 元素。



我估计你可以在< span> 里面添加一个按钮或东西,只需点击一下即可删除它。或其他东西。但这是你的家庭作业。


I have a contenteditable div, something like:

<div id="text" contenteditable="true"></div>

What I would like is to place another div (or span, non-editable) at the start of #text, where the user cannot insert text before it, or even move the cursor before it.

I've tried variations of:

<div id="text" contenteditable="true">
    <span class="lead" contenteditable="false">This is some leader</span>
</div>

You can see a running version of this setup here.

One thing you'll notice is that I've inserted a blank character &#8203; after the </span>. Without it, the cursor (carrot) does not display properly - either in the wrong spot, or not at all.

I'm not sure why, but in the fiddle I've provided, you cannot delete (backspace) the span content. When I have this identical html running in my browser, from an HTML file, I can delete it. I would like the user to be able to delete it, if desired, but to not allow anything to be inserted in front of it. It should delete all at once - it's either there as a group (including the &#8203;), or not at all. Hence the contenteditable="false".

EDIT 1

It seems the non-deleting issue is purely the way the HTML is written. I've created a new post here commenting on it. That problem is solved, but the larger issue here is still ripe for the taking!

/EDIT 1

The closest I've gotten, using JS, is something like:

$('#testing').on('keyup', function(e){
    if($(this).html().indexOf(... leader ...) == 3){ // Needs to be 3, because the actual content of an editable div has markup in it

    }else{
        var splits = $(this).html().split(... leader ...);

        $(this).html(... leader ...);

        for(var i = 0; i < splits.length; i++){
            $(this).append(splits[i]);
        }
    }
});

which you can see running here.

What it does is checks to see if the desired bit is at the front. If not, it splits the content, and rearranges it so that the desired bit is back at the lead.

It's super buggy, has a lag after keyup, and prints the character before moving it around. It also doesn't work for the desired <span> element previously discussed, and also keeps the cursor at the start of the input field if it began there.

Sorry if I've presented it confusingly. I'm trying to think of a service that offers the same functionality, but can't think of any off the top of my head. FaceBook has something similar, when you type a friend's name into a comment box, but the content is editable and can be anywhere in the input. Shown below:

Thoughts? Anything to get me in the right direction is welcome!

解决方案

SOLUTION!

Tada! <- Link to Fiddle (if too subtle)

This gal does EXACTLY what I'd like her do to, no questions asked.

First off, let us thank this post and this post for getting us on the right track.

Now, how it works:

HTML

Pretty easy setup here, almost identical to what I had originally, but all one line now.

<div id="testing" contenteditable="true"><span contenteditable="false" class="lead">Something something</span>&#8203;</div>

NOTE!! If you want to be able to delete the preceding <span>, you MUST put everything on a single line. Refer to EDIT 1.

CSS

Nothing special about this stuff, would work with or without it. Just how I've set it up, for the time being. Modify as you please.

#testing {
    padding: 5px;
    width: 90%;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    font-size: 13px;
    color: #3B3B3B;
    margin: 0px 0px 15px 0px;
    resize: none;
    overflow: hidden;
    background-color: #FAFAFA;
    line-height: 15px;
    min-height: 42px;
    max-height: 160px;
    outline: none;
}
.lead {
    color: #000;
    background: #ccd;
    padding: 1px 2px 1px 2px;
    font-size: 12px;
    margin-right: 4px;
    border: none;
    -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none;   /* Chrome/Safari/Opera */
    -khtml-user-select: none;    /* Konqueror */
    -moz-user-select: none;      /* Firefox */
    -ms-user-select: none;       /* Internet Explorer/Edge */
    user-select: none;    
}

JS

This is the meat and potatoes of the whole thing! I'm not going to cover the snippets of code from the two sources I mentioned, so deal with that yourself.

Variables

var somethingVisible = true;
var somethingsomething = '<span contenteditable="false" class="lead">Something something</span>&#8203;';
var spanContLen = $('.lead').html().length + 1;

somethingVisible (sV, henceforth) is to keep track of whether the <span> element is a child of the contenteditable div.

somethingsomething (ss, henceforth) is the <span> element, in entirety.

spanContLen (scl, henceforth) is the length of the text within the <span> element, plus 1 for the blank character. This is used for comparing the position of the cursor/caret.

And then the rest...

$('#testing').on('keydown', function(e){
    if(somethingVisible){
        var pos = getCaretPosition(this);
        if(pos < spanContLen){
            setPos(this);
        }

        if(pos <= spanContLen && e.keyCode == 8){
            $('.lead').remove();
            somethingVisible = false;
        }
    }
}).on('keyup', function(e){
    if(somethingVisible){
        var pos = getCaretPosition(this);
        if(pos < spanContLen){
            setPos(this);
        }
    }
}).on('click', function(e){
    if(somethingVisible){
        var pos = getCaretPosition(this);
        if(pos < spanContLen){
            setPos(this);
        }
    }
});

Not too bad, huh!?

Basically, it works like this:

  • If the user types, or clicks, in a position less than sol, move the cursor to the first spot after the <span>.
  • The keydown is particularly great at preventing the user from being a ninja, where they press a character key almost simultaneously as the up-arrow (this has the effect of placing a character before the <span> before the cursor has been programatically moved back)
  • If the cursor is in the scl position, or lower, and the user presses the backspace key (keyCode == 8), then remove the <span> element, and set sV to false.

It isn't perfect, I'm sure, but it works how I'd like it to. A user could be a giant, gaping butt, and disable their JS to get around the system. That's where you need to sanitize your input (duh!) to make sure your user isn't trying to wreck your stuff.

In the fiddle linked above, the "Add Back" button is there simply to insert a new <span> element, should you choose to delete the stock one.

I reckon you could add a button or something inside of the <span>, what for removing it with a click. Or other things. But that's all homework for you.

这篇关于HTML,CSS,JS - 具有永久领先内容的Contenteditable div的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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