修改选择对象

问题描述 投票:3回答:2

目前存在以下问题,我正在使用CKEDITOR 4.x中的applyStyle方法应用跨度标签。但是,当部分跨度被选中并且我执行applyStyle方法时,将通过选择进行新的跨度,但是所选跨度的另一半不会恢复,并且会丢失其跨度。

第一个问题:是否可以防止某些元素的部分选择?

如果不是我的第二个问题:是否可以仅在一侧(部分跨度(具有特定类或属性)的一侧)扩展选择范围。这样便可以完全选择要进行处理。

一个例子:

This is 'my text <span class"testClass">, This' is </span> Other Text

现在我们要创建一个解决方案:

This is  <span class"testClass2"> my text, This</span> <span class"testClass">  is </span> Other Text

请注意以下几点:

其中的难点是维护html结构。如果选择的一半在另一个块级元素中,则可能不会刹车!这就是我开始使用applyStyle方法的原因。

ckeditor range
2个回答
3
投票

第一个问题:是否可以防止某些元素的部分选择?

嗯...您可以检查占位符插件的示例-它使用不可编辑的内联元素来创建至少在Chrome上不能被部分选择的那些占位符。不过,我认为这对您来说不是一个令人满意的解决方案:)

[另一种可能的解决方案是使用editor#selectionChange事件,您可以在该事件上检查选择端之一是否位于该元素内,如果是,则在该元素之前或之后进行设置。看起来像(我还没有测试这段代码,这只是一个原型):

editor.on( 'selectionChange', function( evt ) {
    var sel = evt.data.selection,
        range = sel.getRanges()[ 0 ];

    if ( protectedElement.contains( range.startContainer ) || protectedElement.equals( range.startContainer ) )
        range.setStartAt( protectedElement, CKEDITOR.POSITION_BEFORE_START );
    if ( protectedElement.contains( range.endContainer ) || protectedElement.equals( range.endContainer ) )
        range.setEndAt( protectedElement, CKEDITOR.POSITION_AFTER_END );

    sel.selectRanges( [ range ] );
} );

尽管,这种解决方案始终很危险,并且可能导致许多不可预测的情况。但这可能值得检查。

回到问题的根源-我知道您想创建在相同级别上使用的样式-即,一个地方只能应用一种样式。使用样式系统是不可能的。在应用样式之前,您必须准备范围。该代码类似于selectionChange侦听器-您检查是否在样式元素中锚定了末端,如果是,则需要将范围的末端移出它。唯一的问题是在这种情况下如何从范围中排除整个元素:

<p>foo[bar<span class="st1">bom</span>bim]foo</p>

结果应为两个范围:

<p>foo[bar]<span class="st1">bom</span>[bim]foo</p>

[不幸的是,当前范围的API不包括像range#exclude这样的有用方法,因此您需要实现自己的方法。我会尝试使用walker执行此操作。从范围的开始到结束进行迭代,并记住所有样式元素。如果您将在两个方向上都这样做,那么您还将在两端收集部分选择的元素,因此,我描述的第一步将是不必要的。当您具有要从范围中排除的元素列表时,则只需要在两端以及这些元素之间创建范围-这部分应该很容易。 Element#getPosition会很有帮助,但是您需要检查其代码以了解如何使用它,因为未记录它。


1
投票

我一直在寻找并尝试了几个小时。并选择自己做一个放大功能来扩展选择。我做了自己的放大/扩展功能,因为我想拥有更多CKEDITOR的扩展不提供的控件。

代码:

            //Vars
        var firstNode = range.startContainer.getParent();
        var lastNode = range.endContainer.getParent();

        //Make end Get full if is tcElement
        if(lastNode.type === CKEDITOR.NODE_ELEMENT && lastNode.getName() === "myElement")
        {
            range.setEndAfter(lastNode);

        }

        //Make end Get full if is tcElement
        if(firstNode.type === CKEDITOR.NODE_ELEMENT && firstNode.getName() === "myElement")
        {
            range.setStartBefore(firstNode);
        }

        range.select();

其他不错的代码,虽然不是很难,但对其他人可能有用。

此代码我通常将代码分为2或3部分。如果存在,则部分1和3是部分选择。

            Spliting to multiple ranges
        //Vars
        var newRanges = [];
        var allWithinRangeParent = range.getCommonAncestor().getChildren();
        var firstNode = range.startContainer;
        var lastNode = range.endContainer;
        var firstNodeStart = range.startOffset;
        var lastNodeEnd = range.endOffset;

        //TODO make if to check if this needs to be made.
        //make end partial
        var newEndRange = new CKEDITOR.dom.range( editor.document );
        newEndRange.selectNodeContents( lastNode );
        newEndRange.endOffset = lastNodeEnd;
        newRanges.push(newEndRange);

        //TODO make if to check if this needs to be made.
        //Make start partial
        var newStartRange = new CKEDITOR.dom.range( editor.document );
        newStartRange.selectNodeContents( firstNode );
        newStartRange.startOffset = firstNodeStart;
        newRanges.push(newStartRange);

        //Make center selection.
        var tempRange = new CKEDITOR.dom.range( editor.document );
        tempRange.setStartBefore(firstNode.getParent().getNext());
        tempRange.setEndAfter(lastNode.getParent().getPrevious());
        newRanges.push(tempRange);

        selection.selectRanges(newRanges);
© www.soinside.com 2019 - 2024. All rights reserved.