CKEditor 4.7: возможно ли применять класс css к определенным элементам только в режиме WYSIWYG?

Можно ли использовать другую функцию CKEditor, чтобы добавить только класс css для режима wysiwyg во время редактирования (а не для результирующего содержимого)? (Подобно тому, как проверка орфографии /scayt добавляет диапазон с волнистыми стилями подчеркивания только в режиме wysiwyg)

Мой разыскиваемый сценарий

Я создал плагин для CKEditor 4.7, который ищет определенные теги с определенным содержимым (например, пустой абзац, который может привести к непреднамеренным "пробелам" на конечном веб-сайте) и добавляет класс css к тегам. Класс добавляет красную рамку, чтобы сообщить редактору о "пустом" теге. Я на самом деле использую editor.document.$.getElementsByTagName(tagName); и простой JavaScript, чтобы добавить класс CSS rte-empty,

Моя проблема

Мой подход добавляет класс CSS также к окончательному содержанию <textarea />,

Вот мой код при публикации вопроса:

/**
 * Check for empty tags plugin
 */

'use strict';

(function () {
 CKEDITOR.plugins.add('emptytags', {
  lang: "de,en",
  onLoad: function(editor) {
   CKEDITOR.addCss(
    '.cke_editable .rte-empty {' +
     ' border: 1px dotted red;' +
    '}'
   );
  },
  init: function (editor) {

   // Default Config
   var defaultConfig = {
    tagsToCheck: {0: 'p'}
   };
   var config = CKEDITOR.tools.extend(defaultConfig, editor.config.emptytags || {}, true);

   editor.addCommand('checkForEmptyTags', {
    exec: function (editor) {
     var editorContent = editor.getData();
     // Stop check and inform editor if the editor has no content.
     if (editorContent === '') {
      alert(editor.lang.emptytags.AlertEditorContentEmpty)
      return;
     }
     // Check if tag name's to check are set
     if (config.tagsToCheck.length > 0 && config.tagsToCheck[0] !== null) {
      var index;
      for (index = 0; index < config.tagsToCheck.length; ++index) {
       var tagName = config.tagsToCheck[index];
       var tags = editor.document.$.getElementsByTagName(tagName);
       for (var i=0; i < tags.length; i++) {
        if (checkForRealEmptyTag(tags[i].innerHTML)
         || checkForEmptyTagWithSpace(tags[i].innerHTML)
         || checkForEmptyTagWithNbsp(tags[i].innerHTML)
        ) {
         if(tags[i].className.indexOf("rte-empty") < 0){
          tags[i].className += "rte-empty";
         }
         var noEmptyTagFound = false;
        } else {
         tags[i].classList.remove("rte-empty");
        }
       }
      }
      // Inform editor that no empty tag can be found (anymore)
      if (noEmptyTagFound === true) {
       alert(editor.lang.emptytags.AlertEditorNoEmptyTagFound);
      }
     }
    }
   });
   editor.ui.addButton && editor.ui.addButton('Check for empty tags', {
    label: editor.lang.emptytags.ToolbarButton,
    command: 'checkForEmptyTags',
    toolbar: 'insertcharacters'
   });
  }
 });

 function checkForRealEmptyTag(content) {
  return content.length === 0;

 }

 function checkForEmptyTagWithNbsp(content) {
  return content === '&nbsp;' || content.trim() === '<br>';
 }

 function checkForEmptyTagWithSpace(content) {
  return content.trim().length === 0;
 }

})();

Следовательно

Я ищу такую ​​возможность, как это делает плагин SCAYT: добавление тегов span с классом для добавления волнистого подчеркивания к словам, которые не могут быть найдены в словарях.

1 ответ

Я бы лично послушал события toDataFormat и toHtml, чтобы добавить, а затем удалить класс CSS для элементов, которые вы хотите. Таким образом, пользователь не увидит класс при получении данных обратно из CKEditor или при переключении в режим источника.

Вот обновленный код (вам все еще нужно настроить его в соответствии с вашими потребностями):

CKEDITOR.plugins.add('emptytags', {
    lang: "de,en",
    onLoad: function(editor) {
        CKEDITOR.addCss(
        '.cke_editable .rte-empty {' +
            ' border: 1px dotted red;' +
        '}'
        );
    },
    init: function (editor) {

        editor.on('toHtml', function (evt) {

            markEmptyChildren(evt.data.dataValue);

        }, null, null, 14);

        editor.on('toDataFormat', function (evt) {

            unmarkEmptyChildren(evt.data.dataValue);

        },
        null, null, 14);

        function markEmptyChildren(element) {
            var children = element.children;
            if (children) {
                for (var i = children.length; i--; ) {
                var child = children[i];
                if (child.name == "p") {
                    if (isEmpty(child)) {
                    child.addClass("rte-empty")
                    } else {
                    child.removeClass("rte-empty")
                    }
                }
                markEmptyChildren(child);
                }
            }
        }

        function unmarkEmptyChildren(element) {
            var children = element.children;
            if (children) {
                for (var i = children.length; i--; ) {
                var child = children[i];
                if (child.name == "p") {
                    child.removeClass("rte-empty")
                }
                unmarkEmptyChildren(child);
                }
            }
        }

        function isEmpty(node) {

            if (node instanceof CKEDITOR.htmlParser.element) {
                if (node.name == "br") {
                    return true;
                } else {
                    var children = node.children;
                    for (var i = children.length; i--; ) {
                        var child = children[i];
                        if (!isEmpty(children[i])) {
                            return false;
                        }
                    }
                    return true;
                }
            } else if (node instanceof CKEDITOR.htmlParser.text) {
                return node.value.trim().length === 0;
            } else {
                return true;
            }

        }
    }
});

Смотрите JSFiddle здесь.

Другие вопросы по тегам