亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

不可編輯的內容允許刪除。如何限制這個?

不可編輯的內容允許刪除。如何限制這個?

江戶川亂折騰 2023-05-19 16:15:30
我們使用了帶有“不可編輯”插件的 TinyMCE 編輯器。我們嘗試刪除不可編輯的內容,它被刪除了。如何限制不可編輯內容的刪除(刪除/退格)操作?下面是我的代碼:tinymce.init({  selector: "#myeditablediv",  plugins: "advlist table lists image paste link pagebreak noneditable help",  noneditable_noneditable_class: "mceNonEditable",  menubar: false,  inline: true,  height: 500,  paste_data_images: true,  toolbar_sticky: true,  toolbar:    "bold italic underline | superscript subscript | formatselect | bullist | code pagebreak | link image | COC | table | removeformat | help",  formats: {    editable: {      inline: "span",      styles: { borderBottom: "2px solid gray" },      classes: "mceEditable"    }  },  setup: function (editor) {    editor.ui.registry.addButton("COC", {      text: "<b style='font-size:large;font-weight:bold;'>{CC}</b>",      tooltip: "CopyToClipBoard",      onAction: function (api) {        editor.execCommand("Copy");      }    });  },  toolbar_mode: "floating"});<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/5/tinymce.min.js"></script><div class="demo-inline">  <div id="myeditablediv">    Hi tiny    <p class='mceNonEditable'> <b> This is a non editable content</b>    </p>    <p> <span class='mceNonEditable'> <b>This part is non editable</b> </span>      This is a editable content      <span class='mceNonEditable'> <b>This part is non editable</b> </span>    </p>  </div></div>
查看完整描述

2 回答

?
嗶嗶one

TA貢獻1854條經驗 獲得超8個贊

TinyMCE 的noneditable插件旨在使內容塊不可編輯,但不可刪除。相反,它將不可編輯內容的整個部分視為單個字符。

要阻止內容被鍵盤刪除,您可以使用 Tiny 的事件處理結構來查找某些按鍵,然后中斷/停止它們。

您需要展開它以查看光標在內容中的位置,如果按鍵的結果會刪除您想要保留的內容,則僅在這些情況下停止按鍵。

請注意,此方法不會阻止通過其他方法刪除內容,例如將其作為更大選擇的一部分刪除。


查看完整回答
反對 回復 2023-05-19
?
溫溫醬

TA貢獻1752條經驗 獲得超4個贊

編寫了一個到目前為止運行良好的 Angular 服務,可能需要針對邊緣情況進行一些調整。nonDeletableSelectors包含表示應該不可刪除的元素的 CSS 選擇器。我注意到顯然有一個帶有不可編輯元素的 TinyMCE 錯誤,所以代碼比我想象的更復雜。

import {Injectable} from '@angular/core';


@Injectable({

? providedIn: 'root'

})

export class EditorPreventDeleteService {


? constructor() { }


? public nonDeletableSelectors = ['.mceNonEditable'];


? public preventDelete(editor) {

? ? let self = this;

? ? editor.on('keydown', function(event) {

? ? ? if (self.keyWillDelete(event)) {

? ? ? ? let range = editor.selection.getRng(), selection = editor.selection.getSel();

? ? ? ? if (!range.collapsed)

? ? ? ? ? return self.checkSelection(editor, event);

? ? ? ? else if (event.keyCode == 8)

? ? ? ? ? self.checkBackspace(editor, event, selection);

? ? ? ? else if (event.keyCode == 46)

? ? ? ? ? self.checkDelete(editor, event, selection);

? ? ? }

? ? ? return true;

? ? });

? ? editor.on('beforeSetContent', event => {

? ? ? return self.checkSelection(editor, event);

? ? });

? ? editor.on('dragstart', event => {

? ? ? if (self.checkNode(event.target, true))

? ? ? ? self.cancelEvent(event);

? ? });

? }


? protected checkNode(node, includeChildren = true) {

? ? if (node && node.nodeType !== Node.TEXT_NODE)

? ? ? for (let nonDeletableSelector of this.nonDeletableSelectors)

? ? ? ? if (node.matches(nonDeletableSelector)

? ? ? ? ? ? || (includeChildren && node.querySelectorAll(nonDeletableSelector).length > 0))

? ? ? ? ? return true;

? ? return false;

? }


? protected checkSelection(editor, event) {

? ? const selectedHTMLString = editor.selection.getContent({format : 'html'});

? ? const selectedHTML = new DOMParser().parseFromString(selectedHTMLString, 'text/html').documentElement;

? ? if (this.checkNode(selectedHTML))

? ? ? return this.cancelEvent(event);

? ? return true;

? }


? protected checkBackspace(editor, event, selection) {

? ? if (selection.anchorOffset === 0 && this.getPrefixContent(editor, selection).length === 0)

? ? ? return this.cancelEvent(event);

? ? this.checkCaretDeletion(editor, event, selection, false);

? }


? protected checkDelete(editor, event, selection) {

? ? this.checkCaretDeletion(editor, event, selection, true);

? }


? protected checkCaretDeletion(editor, event, selection, forwards = true) { // https://developer.mozilla.org/en-US/docs/Web/API/Selection

? ? let borderingElement = forwards ? selection.anchorNode.nextSibling : selection.anchorNode.previousSibling;

? ? if (selection.anchorNode.nodeType === Node.TEXT_NODE) {

? ? ? if (this.getTrailingText(selection, forwards, false).length > 0)

? ? ? ? return; // not at the border of a text element

? ? } else if (selection.anchorOffset !== (forwards ? selection.anchorNode.childNodes.length : 0)

? ? ? ? && this.trimZeroWidthSpaces(selection.anchorNode.textContent).length > 0

? ? ? ? && this.checkNode(selection.anchorNode.childNodes.item(selection.anchorOffset + (forwards?0:1))))

? ? ? ? return this.cancelEvent(event); // not at the border of anchor, anchor not empty, only neighbouring child is deleted

? ? if (this.checkNode(selection.anchorNode) || this.checkNode(borderingElement))

? ? ? this.cancelEvent(event);

? }


? protected getPrefixContent(editor, selection) {

? ? let currentRange = editor.selection.getRng(1), tempRange = currentRange.cloneRange();

? ? tempRange.setStartBefore(editor.getBody().childNodes.item(0));

? ? tempRange.setEndBefore(selection.anchorNode);

? ? editor.selection.setRng(tempRange);

? ? let content = editor.selection.getContent({format: 'html'});

? ? editor.selection.setRng(currentRange);

? ? return this.trimZeroWidthSpaces(content.trim());

? }


? protected getTrailingText(selection, forwards = true, includeSiblings = false) {

? ? let trailer = '', appendTrailer = function(text) { forwards ? trailer += text : trailer = text + trailer; }

? ? if (selection.anchorNode.nodeType === Node.TEXT_NODE) {

? ? ? let text = selection.anchorNode.textContent;

? ? ? appendTrailer(forwards ? text.substr(selection.anchorOffset) : text.substr(0, selection.anchorOffset));

? ? } else {

? ? ? for (let i=selection.anchorOffset ; i>=0 && i<selection.anchorNode.childNodes.length ; i+=(forwards?-1:1))

? ? ? ? appendTrailer(selection.anchorNode.childNodes.item(i).textContent);

? ? }

? ? if (includeSiblings) {

? ? ? let sibling = selection.anchorNode.previousSibling;

? ? ? while (sibling) {

? ? ? ? appendTrailer(sibling.textContent);

? ? ? ? sibling = sibling.previousSibling;

? ? ? }

? ? }

? ? return this.trimZeroWidthSpaces(trailer);

? }


? protected cancelEvent(event) {

? ? event.preventDefault();

? ? event.stopPropagation();

? ? return false;

? }


? protected keyWillDelete(evt) {

? ? let c = evt.keyCode;

? ? if (evt.ctrlKey)

? ? ? return evt.key == 'x' || [8, 46].includes(c);

? ? return [8, 9, 13, 46].includes(c)

? ? ? ? || this.inRange(c, 48, 57)

? ? ? ? || this.inRange(c, 65, 90)

? ? ? ? || this.inRange(c, 96, 111)

? ? ? ? || this.inRange(c, 186, 192)

? ? ? ? || this.inRange(c, 219, 222);

? }


? protected inRange(val, min, max) {

? ? return val >= min && val <= max;

? }


? protected trimZeroWidthSpaces(text: string) {

? ? return text.replace(/[\u200B-\u200D\uFEFF]/g, '');

? }


}


查看完整回答
反對 回復 2023-05-19
  • 2 回答
  • 0 關注
  • 293 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號