如何阻止关于在CKEDITOR textarea的内容某个部分的编辑?(How to block e

2019-06-26 01:04发布

我有我的CKEDITOR形式预置了其正在与用户inputed文本一并提交隐藏的表。 这工作得很好,但有时用户按下退格太多次,并删除隐藏的表。

有没有办法来阻止对文本区域的CKEditor里面这个隐藏表格编辑? 因此,当用户按下退格键,隐藏的表不会受到影响,并保持英寸

一旦CKEDITOR实例准备这个源(波纹管)CKEDITOR textarea的内部被放置(使用使用setData()属性)和用户只看到返回的<p></p>值。 在这种情况下,它<p>I really think I can do this!</p> 其他的个人资料的描述,他可以把它和编辑它。 其余的是隐藏的,只可见电子邮件的形式提交时。 它的奇怪的是, <p></p>是在上面,但如果用户按下退格几次表被删除,并为此未提交。

    <span id="messageTemplate1" class="message">

<p>I really think I can do this!</p>

<table class="hide" style="font-size: 12px;">
    <tbody>
        <tr class="hide">
            <td>
            Application sent by <strong><a href="http://www.globalcastingcenter.com/talent/jack-bolton">Matt Faro</a></strong> for Audition: <a href="http://www.globalcastingcenter.com:80/CustomContentRetrieve.aspx?ID=4185493">Actors Needed</a>
            </td>
        </tr>
        <tr class="hide">
            <td>
            Reply to applicant directly: mantas@mantas.co or visit full profile: http://www.globalcastingcenter.com/talent/jack-bolton
            </td>
        </tr>
    </tbody>
</table>
<table class="hide" style="font-size: 12px;">
    <tbody>
        <tr class="hide">
            <td><strong>Short Profile Summary:</strong></td>
        </tr>
    </tbody>
</table>
<table class="hide" style="font-size: 12px;">
    <tbody>
        <tr class="hide">
            <td>
            <a href="http://www.globalcastingcenter.com/talent/jack-bolton"><img alt="" src="http://globalcastingcenter.com/talent_images/4164035_258551_foto.png?Action=thumbnail&amp;Width=144&amp;Height=215" /></a>
            </td>
        </tr>
    </tbody>
</table>
<table style="font-size: 12px;" class="hide">
    <tbody>
        <tr class="hide">
            <td><strong>Areas:</strong></td>
            <td>Actor,Extra</td>
        </tr>
        <tr class="hide">
            <td><strong>Country:</strong></td>
            <td>WORLDWIDE,Any</td>
        </tr>
        <tr class="hide">
            <td><strong>Age:</strong></td>
            <td>26</td>
        </tr>
    </tbody>
</table>
</span>

现在,当我打开你的插件我CKEDITOR盒在前看不见,请按“应用”的测试页面上http://gcc-july.themantas.co.uk/auditions/actors-needed请先登录才能够访问该消息框登录名称:tiknius@gmail.com pssw:测试

我的配置文件:

CKEDITOR.editorConfig = function( config )
{
    config.toolbar = 'MyToolbar';

    config.toolbar_MyToolbar =
    [

        { name: 'clipboard', items : [ 'Undo','Redo' ] },           
        { name: 'styles', items : ['FontSize' ] },
        { name: 'basicstyles', items : [ 'Bold','Italic'] },
        { name: 'paragraph', items : ['Outdent','Indent' ] },

    ];

    config.removePlugins = 'contextmenu';
    config.forcePasteAsPlainText = true;   
    config.pasteFromWordRemoveFontStyles = true;
    config.pasteFromWordRemoveStyles = true;
    config.extraPlugins = 'cwjdsjcsconfineselection';
    config.startupShowBorders = false;
    config.disableObjectResizing = true;

};

这是盒子的外观,当我禁用插件: http://screencast.com/t/Kc2bIOU8md2

我用你的建议的HTML结构。

Answer 1:

我不得不发挥与它周围一点得到它的工作。 我加了大量的文件到插件代码,如果你读它通过让我知道以后有任何问题。

我包括你的内容块和一个更新版本的插件代码块。


这里是你更新的内容块。 这不是当包裹在工作<span>标签,所以我把它包在表中。

你可以不喜欢的是,数据单元格周围出现边框和调整的轮廓,如果是这样的话,添加这些设置到您的配置:
config.startupShowBorders = false;
config.disableObjectResizing = true;

一些注意事项:
<td>需要你的出发内容之前,它可以防止用户使用“Ctrl键A”选择所有这将让他们删除隐藏的表。

我除去<p>从起始内容标签,因为它作用在此结构中时髦。

所述<td>保持所述隐藏的表具有&nbsp; 字符,它可以防止用户使用“Ctrl键A”选择所有这将让他们删除表中隐藏。 它会导致如果删除一切光标向右移动光标迷路,但你可以在内容点击重新开始编辑。

contenteditable="false"属性由CKEDITOR并且是需要的,但它不会做的整个工作。 你可以尝试新的HTML不激活插件,看看它有什么作用本身。

还有约我使用的类和ID插件代码注释。

<!-- Begin Wrapper Table that Replaces <span> element -->
<table id="messageTemplate1" class="message cwjdsjcs_editable">
    <tbody>
        <tr>
            <td class="cwjdsjcs_not_editable" contenteditable="false">
            </td>
            <td id="cwjdsjcs_editable_id">
                I really think I can do this!
            </td>
        </tr>

        <tr class="cwjdsjcs_not_editable" contenteditable="false">
            <td colspan="2">
                &nbsp;

                <!-- Begin Original Content -->
                <table class="hide" style="font-size: 12px; display:none;">
                    <tbody>
                        <tr class="hide">
                            <td>
                            Application sent by <strong><a href="http://www.globalcastingcenter.com/talent/jack-bolton">Matt Faro</a></strong> for Audition: <a href="http://www.globalcastingcenter.com:80/CustomContentRetrieve.aspx?ID=4185493">Actors Needed</a>
                            </td>
                        </tr>
                        <tr class="hide">
                            <td>
                            Reply to applicant directly: mantas@mantas.co or visit full profile: http://www.globalcastingcenter.com/talent/jack-bolton
                            </td>
                        </tr>
                    </tbody>
                </table>
                <table class="hide" style="font-size: 12px; display:none;">
                    <tbody>
                        <tr class="hide">
                            <td><strong>Short Profile Summary:</strong></td>
                        </tr>
                    </tbody>
                </table>
                <table class="hide" style="font-size: 12px; display:none;">
                    <tbody>
                        <tr class="hide">
                            <td>
                            <a href="http://www.globalcastingcenter.com/talent/jack-bolton"><img alt="" src="http://globalcastingcenter.com/talent_images/4164035_258551_foto.png?Action=thumbnail&amp;Width=144&amp;Height=215" /></a>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <table style="font-size: 12px; display:none;" class="hide">
                    <tbody>
                        <tr class="hide">
                            <td><strong>Areas:</strong></td>
                            <td>Actor,Extra</td>
                        </tr>
                        <tr class="hide">
                            <td><strong>Country:</strong></td>
                            <td>WORLDWIDE,Any</td>
                        </tr>
                        <tr class="hide">
                            <td><strong>Age:</strong></td>
                            <td>26</td>
                        </tr>
                    </tbody>
                </table>
                <!-- End Original Content -->

            </td>
        </tr>
    </tbody>
</table>
<!-- End Wrapper Table that Replaces <span> element -->

这里的插件代码,这就是所谓的“cwjdsjcsconfineselection”。

要添加插件:
创建一个名为在plugins目录“cwjdsjcsconfineselection”文件夹: ckeditor/plugins/
创建在该目录中称为“plugins.js”文件,并粘贴下面的代码到该文件。 我的错误:文件名为plugin.js,没有插件(S)的.js。

如果你已经有额外的插件,加上“cwjdsjcsconfineselection”到extraPlugins配置设置,否则此设置添加到您的配置:
config.extraPlugins = 'cwjdsjcsconfineselection';

该插件应该工作,你加载编辑器的下一次。

对于我的情况,我有当用户点击一个不可编辑的区域来解释为什么光标移回以前的选择对话框出现。 这似乎没有必要为您的使用情况,所以我评论一下。

/*
  Plugin that prevents editing of elements with the "non-editable" class as well as elements outside of blocks with "editable" class.
*/

//* **************************  NOTES  ***************************  NOTES  ****************************
/*
  The "lastSelectedElement" variable is used to store the last element selected.

  This plugin uses the "elementspath" plugin which shows all elements in the DOM
  parent tree relative to the current selection in the editing area.

  When the selection changes, "elementsPathUpdate" is fired,
  we key on this and loop through the elements in the tree checking the classes assigned to each element.

  Three outcomes are possible.

  1) The non-editable class is found:
  Looping stops, the current action is cancelled and the cursor is moved to the previous selection.
  The "selectionChange" hook is fired to set the reverted selection throughout the instance.

  2) The editable class is found during looping, the "in_editable_area" flag is set to true.

  3) Neither the editable or the non-editable classes are found (user clicked outside your main container).
  The "in_editable_area" flag remains set to false.

  If the "in_editable_area" flag is false, the current action is cancelled and the cursor is moved to the previous location.
  The "selectionChange" hook is fired to set the reverted selection throughout the instance.

  If the "in_editable_area" flag is true,
  the "lastSelectedElement" is updated to the currently selected element and the plugin returns true.

---------------
  If you don't want the elements path to be displayed at the bottom of the editor window,
  you can hide it with CSS rather than disabling the "elementspath" plugin.

  The elementspath plugin creates and is left active because we are keying on changes to the path in our plugin.
  #cke_path_content
  {
    visibility: hidden !important;
  }

---------------
  CSS Classes and ID that the plugin keys on. Use defaults or update variables to use your preferred classes and ID:

  var starting_element_id = ID of known editable element that always occurs in the instance.
  Don't use elements like <table>, <tr>, <br /> that don't contain HTML text.
  Default value = cwjdsjcs_editable_id

  var editable_class = class of editable containers.
  Should be applied to all top level elements that contain editable elements.
  Default = cwjdsjcs_editable

  var non_editable_class = class of non-editable elements within editable containers
  Apply to elements where all child elements are non-editable.
  Default = cwjdsjcs_not_editable

*/

//* **************************  END NOTES  ***************************  END NOTES  ****************************


// Register the plugin with the editor.
// http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.plugins.html
CKEDITOR.plugins.add( 'cwjdsjcsconfineselection',
{
  requires : [ 'elementspath' ],

  // The plugin initialization logic goes inside this method.
  // http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.pluginDefinition.html#init
  init: function( editor )
  {
    editor.on( 'instanceReady', function( instance_ready_data )
    {
      // Create variable that will hold the last allowed selection (for use when a non-editable selection is made)
      var lastSelectedElement;
      editor.cwjdsjcs_just_updated = false;

      // This section starts things off right by selecting a known editable element.
      // *** Enter the ID of the element that should have initial focus *** IMPORTANT *** IMPORTANT ***
      var starting_element_id = "cwjdsjcs_editable_id";

      var resInitialRange = new CKEDITOR.dom.range( editor.document );

      resInitialRange.selectNodeContents( editor.document.getById( starting_element_id ) );
      resInitialRange.collapse();

      var selectionObject = new CKEDITOR.dom.selection( editor.document );

      editor.document.focus();
      selectionObject.selectRanges( [ resInitialRange ] );

      var sel = editor.getSelection();
      var firstElement = sel.getStartElement();
      var currentPath = new CKEDITOR.dom.elementPath( firstElement );

      // Set path for known editable element, fire "selectionChange" hook to update selection throughout instance.
      editor._.selectionPreviousPath = currentPath;
      editor.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );
    }); // *** END - editor.on( 'instanceReady', function( e )


    // When a new element is selected by the user, check if it's ok for them to edit it,
    // if not move cursor back to last know editable selection
    editor.on( 'elementsPathUpdate', function( resPath )
    {
      // When we fire the "selectionChange" hook at the end of this code block, the "elementsPathUpdate" hook fires.
      // No need to check because we just updated the selection, so bypass processing.
      if( editor.cwjdsjcs_just_updated == true )
      {
        editor.cwjdsjcs_just_updated = false;
        return true;
      }

      var elementsList = editor._.elementsPath.list;
      var in_editable_area = false;
      var non_editable_class = "cwjdsjcs_not_editable";
      var editable_class = "cwjdsjcs_editable";

      for(var w=0;w<elementsList.length;w++){
        var currentElement = elementsList[w];

        // Sometimes a non content element is selected, catch them and return selection to editable area.
        if(w == 0)
        {
          // Could change to switch.
          if( currentElement.getName() == "tbody" )
          {
            in_editable_area = false;
            break;
          }

          if( currentElement.getName() == "tr" )
          {
            in_editable_area = false;
            break;
          }
        }

        // If selection is inside a non-editable element, break from loop and reset selection.
        if( currentElement.hasClass(non_editable_class) )
        {
          in_editable_area = false;
          break;
        }

        if( currentElement.hasClass(editable_class) ) {
          in_editable_area = true;
        }
        console.log(currentElement);
        console.log(currentElement.getName());
      }

      // if selection is within an editable element, exit the plugin, otherwise reset selection.
      if( in_editable_area ) {
        lastSelectedElement = elementsList[0];
        return true;
      }

      var resRange = new CKEDITOR.dom.range( editor.document );

      resRange.selectNodeContents( lastSelectedElement );
      resRange.collapse();
      editor.getSelection().selectRanges( [ resRange ] );
      resRange.endContainer.$.scrollIntoView();

      // Open dialog window:
      // It tells user they selected a non-editable area and cursor has been returned to previous selection
//      currentEditorName = editor.name;
//      openResDefaultDialog(currentEditorName);

      try
      {
        var sel = editor.getSelection();
        var firstElement = sel.getStartElement();
        var currentPath = new CKEDITOR.dom.elementPath( firstElement );
        editor.cwjdsjcs_just_updated = true;

        editor._.selectionPreviousPath = currentPath;
        editor.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );

      }
      catch (e)
      {}
    });
  } // *** END - init: function( editor )
}); // ************************************************************************************* END - CKEDITOR.plugins.add

为了测试该插件加载的实例,准备触发后添加一个通知:

    editor.on( 'instanceReady', function( instance_ready_data )
    {
      alert("instanceReady");

为了测试该插件被触发时选择的变化,elementsPathUpdate触发后添加一个通知:

    editor.on( 'elementsPathUpdate', function( resPath )
    {
      alert("elementsPathUpdate");


Answer 2:

我知道这是封闭和解决,但这里有一个选项:

添加表格只是在时间,用户提交表单或者然而正在使用您的CKE内容之后。 只是不添加隐形表,但是当用户点击“提交”,然后将其添加到任何被公布。 另外,如果以后需要修改它,只需插入到编辑器之前删除它,然后在发布前再次添加它的正是时候。 作为动作发生CKE外CKE核心的无盗号无插件需要。



Answer 3:

我也有类似的要求,但并没有在网上找到我的答案。

在我的情况,我想通过添加支持编辑器中的制表符pre的内容元素:

editor.on('key', function(ev) {
    if (ev.data.keyCode == 9) { // TAB
        // data-tab attribute added so we can identify it later
        var tabHtml = '<pre data-tab="true" style="display:inline;">&#09;</pre>';
        var tabElement = CKEDITOR.dom.element.createFromHtml(tabHtml, editor.document);
        editor.insertElement(tabElement);
        ev.cancel();
    }
});

但现在用户可以使用方向键或单击鼠标,并开始内部编辑pre元素。 所以,我听“点击”和“KEYUP”事件,并将光标移动,如果他们是内部pre

// this prevents the user from typing inside the tab span
var moveCursorOutOfTab = function() {
    var ranges = editor.getSelection().getRanges();
    if (ranges.length == 1) {
        var parent = ranges[0].startContainer.getParent();

        // is the cursor is inside a tab element
        if (parent && parent.getAttribute('data-tab') == 'true') {
            var newRange = editor.createRange();
            newRange.setStartAfter(parent);
            newRange.setEndAfter(parent);

            // move the cursor after the tab element
            editor.getSelection().selectRanges([newRange]);
        }
    }
};

// wait until the editor is initialized
editor.on('contentDom', function() {
    var editable = editor.editable();

    // listen for clicks
    editable.attachListener(editable, 'click', function(ev) {
        moveCursorOutOfTab();
    });

    // must use the keyup event because we want to
    // act after any cursor movements
    editor.document.on('keyup', function(ev) {
        // check for left and right arrow keys
        if (ev.data.getKey() == 37 || ev.data.getKey() == 39) {
            moveCursorOutOfTab();
        }
    });
});


文章来源: How to block editing on certain part of content in CKEDITOR textarea?