1

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

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

编辑 1:
我创建了一个基本库来满足我的需要,但我认为我在这个库上使用了我所有糟糕的 js 技能......它可以在 div 上运行,contenteditable=true但我很难让它在 wysihtml5 编辑器上运行. 一些 javascript/wysihtml5/rangy ninja 可以给我一些帮助吗?

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

编辑2:
第一个工作版本:http: //jsfiddle.net/X9jBM/1/

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

仍然想听听对此的一些反馈。

4

1 回答 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);
});

有一些重构要做,但这是基本思想。

于 2013-12-02T21:18:17.233 回答