Rangy:字母在插入符号(再次) [英] Rangy: word under caret (again)

查看:246
本文介绍了Rangy:字母在插入符号(再次)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个前缀代码来添加到wysihtml5富文本编辑器。
基本上,我需要能够插入像Twitter / Github / Facebook ...这样的People / hashtag引用。



我发现一些人尝试的代码实现同样的事情。



http:// jsfiddle .net / A9z3D /



这个工作很好,除了它只对最后一个单词做出建议,并且有一些错误。而我想要一个选择框,如Twitter,而不是一个简单的选择切换使用标签键。



为此,我尝试检测当前键入的单词。 >

  getCurrentlyTypedWord:function(e){
var iframe = this。$(iframe.wysihtml5-sandbox)。get 0);
var sel = rangy.getSelection(iframe);
var word;
if(sel.rangeCount> 0&&sel.isCollapsed){
console.debug(Rangy:,sel);
var initialCaretPositionRange = sel.getRangeAt(0);
var rangeToExpand = initialCaretPositionRange.cloneRange();
var newStartOffset = rangeToExpand.startOffset> 0? rangeToExpand.startOffset - 1:0;
rangeToExpand.setStart(rangeToExpand.startContainer,newStartOffset);
sel.setSingleRange(rangeToExpand);
sel.expand(word,{
trim:true,
wordOptions:{
includeTrailingSpace:true,
// wordRegex:/([a-z0 -9] +)* / gi
wordRegex:/ [a-z0-9] +('[a-z0-9] +)* / gi
// wordRegex:/([a- z0-9] +)* / gi
}
});
word = sel.text();
sel.removeAllRanges();
sel.setSingleRange(initialCaretPositionRange);
} else {
word =noRange;
}
console.debug(WORD =,word);
return word;

只有选择合并时才会触发。
注意事项我不得不处理起始偏移的向后移动,因为如果插入符号在单词的末尾(就像大多数用户正在键入的情况一样),则扩展函数不会' t / p>

到目前为止,这个工作非常好,问题是它使用了Rangy 1.3的alpha版本,它具有 TextRangeModule 。事实是,我注意到wysihtml5也在不同的和不兼容的版本(1.2.2)( rangy.dom 的问题可能已被删除)中使用Rangy。 p>

由于Rangy使用了一个全局的window.rangy变量,我想我将不得不使用1.2.2版本。



如何使用只有rangy 1.2.2的 expand 函数相当于



编辑:顺便说一下,是否有其他解决方案比使用 expand 函数?我认为修改当前选择是有点奇怪,并且将其恢复,只是为了知道当前键入的单词。是不是有一个解决方案,不涉及选择当前键入的单词?我的意思是一旦知道初始插入符合范围,就是基于范围?

解决方案


一个全局的window.rangy变量,我想我将不得不使用版本1.2.2。


读了Rangy的代码,我有直觉,在同一页面中加载两个版本的Rangy可能是可行的。我做了一个谷歌搜索,发现我是对的。 Tim Down(Rangy的创建者)在问题报告中解释。他给了这个例子:

 < script type =text / javascriptsrc =/ rangy-1.0.1 / rangy -core.js>< /脚本> 
< script type =text / javascriptsrc =/ rangy-1.0.1 / rangy-cssclassapplier.js>< / script>

< script type =text / javascript>
var rangy1 = rangy;
< / script>

< script type =text / javascriptsrc =/ rangy-1.1.2 / rangy-core.js>< / script>
< script type =text / javascriptsrc =/ rangy-1.1.2 / rangy-cssclassapplier.js>< / script>

所以你可以加载您的代码需要的Rangy版本。重命名并在代码中使用此名称,然后加载wysihtml5所需的名称,并将 版本留为 rangy



否则,必须实现展开,以忠实地复制Rangy 1.3所做的一切并不简单。



这是一个非常原始的代码实现,可以将选择扩展到字边界。该代码将被单词中的元素开头或结尾所触发。

  var word_sep =; 

函数expand(){
var sel = rangy.getSelection();
var range = sel.getRangeAt(0);

var start_node = range.startContainer;
if(start_node.nodeType === Node.TEXT_NODE){
var sep_at = start_node.nodeValue.lastIndexOf(word_sep,range.startOffset);
range.setStart(start_node,(sep_at!== -1)?sep_at + 1:0);
}

var end_node = range.endContainer;
if(end_node.nodeType === Node.TEXT_NODE){
var sep_at = end_node.nodeValue.indexOf(word_sep,range.endOffset);
range.setEnd(end_node,(sep_at!== -1)?sep_at:range.endContainer.nodeValue.length);
}
sel.setSingleRange(range);
}

这是一个小提琴。这应该在电力1.2.2。 (甚至可以没有运行)。


I'm trying to create a typeahead code to add to a wysihtml5 rich text editor. Basically, I need to be able to insert People/hashtag references like Twitter/Github/Facebook... do.

I found some code of people trying to achieve the same kind of thing.

http://jsfiddle.net/A9z3D/

This works pretty fine except it only do suggestions for the last word and has some bugs. And I want a select box like Twitter, not a simple "selection switching" using the tab key.

For that I tried to detect the currently typed word.

        getCurrentlyTypedWord: function(e) {
            var iframe = this.$("iframe.wysihtml5-sandbox").get(0);
            var sel = rangy.getSelection(iframe);
            var word;
            if (sel.rangeCount > 0 && sel.isCollapsed) {
                console.debug("Rangy: ",sel);
                var initialCaretPositionRange = sel.getRangeAt(0);
                var rangeToExpand = initialCaretPositionRange.cloneRange();
                var newStartOffset = rangeToExpand.startOffset > 0 ? rangeToExpand.startOffset - 1 : 0;
                rangeToExpand.setStart(rangeToExpand.startContainer,newStartOffset);
                sel.setSingleRange(rangeToExpand);
                sel.expand("word", {
                    trim: true,
                    wordOptions: {
                         includeTrailingSpace: true,
                         //wordRegex: /([a-z0-9]+)*/gi
                         wordRegex: /[a-z0-9]+('[a-z0-9]+)*/gi
                        // wordRegex: /([a-z0-9]+)*/gi
                    }
                });
                word = sel.text();
                sel.removeAllRanges();
                sel.setSingleRange(initialCaretPositionRange);
            } else {
                word = "noRange";
            }
            console.debug("WORD=",word);
            return word;

This is only triggered when the selection is collapsed. Notice I had to handle a backward move of the start offset because if the caret is at the end of the word (like it is the case most of the time when an user is typing), then the expand function doesn't expand around the currently typed word.

This works pretty nicely until now, the problem is that it uses the alpha release of Rangy 1.3 which has the TextRangeModule. The matter is that I noticed wysihtml5 is also using Rangy in a different and incompatible version (1.2.2) (problem with rangy.dom that probably has been removed).

As Rangy uses a global window.rangy variable, I think I'll have to use version 1.2.2 anyway.

How can I do an equivalent of the expand function, using only rangy 1.2.2?

Edit: by the way, is there any other solution than using the expand function? I think it is a bit strange and hakish to modify the current selection and revert it back just to know which word is currently typed. Isn't there a solution that doesn't involve selecting the currently typed word? I mean just based on ranges once we know the initial caret collapsed range?

解决方案

As Rangy uses a global window.rangy variable, I think I'll have to use version 1.2.2 anyway.

Having read Rangy's code, I had the intuition that probably it would be feasible to load two versions of Rangy in the same page. I did a google search and found I was right. Tim Down (creator of Rangy) explained it in an issue report. He gave this example:

<script type="text/javascript" src="/rangy-1.0.1/rangy-core.js"></script>
<script type="text/javascript" src="/rangy-1.0.1/rangy-cssclassapplier.js"></script>

<script type="text/javascript">
    var rangy1 = rangy;
</script>

<script type="text/javascript" src="/rangy-1.1.2/rangy-core.js"></script>
<script type="text/javascript" src="/rangy-1.1.2/rangy-cssclassapplier.js"></script>

So you could load the version of Rangy that your code wants. Rename it and use this name in your code, and then load what wysihtml5 wants and leave this version as rangy.

Otherwise, having to implement expand yourself in a way that faithfully replicates what Rangy 1.3 does is not a simple matter.

Here's an extremely primitive implementation of code that would expand selections to word boundaries. This code is going to be tripped by elements starting or ending within words.

var word_sep = " ";

function expand() {
    var sel = rangy.getSelection();
    var range = sel.getRangeAt(0);

    var start_node = range.startContainer;
    if (start_node.nodeType === Node.TEXT_NODE) {
        var sep_at = start_node.nodeValue.lastIndexOf(word_sep, range.startOffset);
        range.setStart(start_node, (sep_at !== -1) ? sep_at + 1 : 0);
    }

    var end_node = range.endContainer;
    if (end_node.nodeType === Node.TEXT_NODE) {
        var sep_at = end_node.nodeValue.indexOf(word_sep, range.endOffset);
        range.setEnd(end_node, (sep_at !== -1) ? sep_at : range.endContainer.nodeValue.length);
    }
    sel.setSingleRange(range);
}

Here's a fiddle for it. This should work in rangy 1.2.2. (It would even work without rangy.)

这篇关于Rangy:字母在插入符号(再次)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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