首页 文章

关于contenteditable = true元素的文本建议

提问于
浏览
1

我正在使用bootstrap-wysihtml5(基于wysihtml5)令人惊叹的编辑器,它工作正常,每个人都很高兴 . 但是现在我需要在用户输入内容时提供文本建议(例如thisthis) . 这些库期望textarea和wysihtml5使用带有 <body contenteditable="true"> 的iframe .

我需要的只是在元素内部的一些纯文本中自动完成(或打开带有建议的弹出窗口)的一些单词 .
在深入研究之前,任何人都有一个可以在 contenteditable="true" 元素内工作的库的建议吗?

Edit 1:
我创建了一个基本的库,可以完成我需要的操作,但我认为我在这个上使用了所有可怜的js技能......它适用于带有 contenteditable=true 的div,但是我很难在wysihtml5编辑器上运行它 . 有些javascript / wysihtml5 / rangy忍者能给我一些帮助吗?

这是我的代码:http://jsfiddle.net/5UQfH/

Edit 2:
第一个工作版:http://jsfiddle.net/X9jBM/1/

Edit 3:
稍微好一点(但不漂亮)版本(适用于同一页面上的多个编辑器):http://jsfiddle.net/X9jBM/18/
当建议是多个单词时仍然无法正常工作(当有空格时停止建议)

仍然希望听到一些关于此的反馈 .

1 回答

  • 1

    我最终创建了一个非常简单的基本库来完成我需要的工作 . 除了最新的chrome版本之外,它不是完美的,也没有经过测试,我可能很容易消除jQuery的依赖性,但是因为我已经把它放在我的项目上(旧的借口),现在我将它保留原样 .
    ENTER 选择一个单词并通过单词循环 TAB . http://jsfiddle.net/X9jBM/19/

    代码:

    if (typeof String.prototype.startsWith != 'function') {
        String.prototype.startsWith = function (str) {
            return this.indexOf(str) == 0;
        };
    }
    
    var SuggestMe = function () {
    "use strict";
    
    var self = this;
    
    return {
        init: init
    };
    
    function init(iframe, words) {
    
        self.list = [];
        self.currentIndex = 0;
        self.currentWord = "";
        self.$iframe = iframe;
        self.$editor = $(iframe).contents().find(".wysihtml5-editor");
    
        self.$editor.on("keydown", function (event) {
    
            if (event.keyCode === 13) {
                var sel = rangy.getIframeSelection(self.$iframe);
    
                if (!sel.isCollapsed) {
                    var range = sel.getRangeAt(0);
                    range.collapse(false);
                    var textNode = document.createTextNode("  ");
                    range.insertNode(textNode);
                    sel.collapseToEnd();
                    event.preventDefault();
                    return false;
                }
            }
    
            if (event.keyCode === 9) {
                var sel = rangy.getIframeSelection(self.$iframe);
                if (!sel.isCollapsed) {
                    self.currentIndex++;
                    var word = self.list[self.currentIndex % self.list.length];
                    var sel = rangy.getIframeSelection(self.$iframe);
                    var range = sel.getRangeAt(0);
                    range.deleteContents();
                    var term = word.slice(self.currentWord.length, word.length);
                    var textNode = document.createTextNode(term);
                    range.insertNode(textNode);
                    range.selectNodeContents(textNode);
                    rangy.getSelection().setSingleRange(range);
    
                    event.preventDefault();
                    return false;
                }
            }
    
        });
    
        self.$editor.on("keyup", function (event) {
    
            var c = String.fromCharCode(event.keyCode);
            var isWordcharacter = c.match(/\w/);
    
            if (isWordcharacter && !event.ctrlKey) {
    
                var $editor = this;
                self.currentWord = getLastWord($editor);
    
                if (self.currentWord) {
                    var sel = rangy.getIframeSelection(self.$iframe);
    
                    if (sel.rangeCount > 0) {
                        self.list = [];
                        self.currentIndex = 0;
    
                        $.each(words, function (a) {
                            var word = words[a].toLowerCase();
    
                            if (word.startsWith(self.currentWord.toLowerCase())) {
                                self.list.push(word);
                            }
                        });
                    }
    
                    if (self.list.length) {
                        var word = self.list[self.currentIndex];
                        var sel = rangy.getIframeSelection(self.$iframe);
                        var range = sel.getRangeAt(0);
                        var term = word.slice(self.currentWord.length, word.length);
                        var textNode = document.createTextNode(term);
                        range.insertNode(textNode);
                        range.selectNodeContents(textNode);
                        rangy.getSelection().setSingleRange(range);
                    }
                }
            }
        });
    }
    
    
    function getLastWord(elm) {
        var val = elm.innerText.trim();
        val = val.replace(/(\r\n|\n|\r)/gm, " ");
        var idx = val.lastIndexOf(' ');
        var lastWord = val.substring(idx + 1).trim();
        console.log(val);
        return lastWord;
    }
    
    };
    

    用法:

    var suggestions = ["hello", "world", "blue dog", "blue cat"];
    
    $('#txt').wysihtml5();
    var editor = $('#txt').data("wysihtml5").editor;
    
    editor.on('load', function () {
        var sm = new SuggestMe();
        sm.init(this.currentView.iframe, suggestions);
    });
    

    有一些重构要做,但这是基本的想法 .

相关问题