【问题标题】:Replacing dumb quotes with smart quotes and keeping caret position in contenteditable div用智能引号替换哑引号并将插入符号位置保留在 contenteditable div
【发布时间】:2014-08-04 02:00:24
【问题描述】:

我正在尝试在 contenteditable div(如 here 所示)中将一些愚蠢的引号动态转换为弯引号,使用以下内容:

$("#editor").on("keyup", ".content", function () {
    $(".content").html(function() {
        var start = this.selectionStart, end = this.selectionEnd;
        return $(this).html()
            .replace(/'\b/g, "\u2018")      // opening single
            .replace(/\b'/g, "\u2019")      // closing single
            .replace(/"\b/g, "\u201c")      // opening double
            .replace(/\b"/g, "\u201d")      // closing double
            .replace(/--/g,  "\u2014")      // em-dash
            .replace(/\b\u2018\b/g,  "'");  // handle conjunctions
        this.setSelectionRange(start, end);
    });
// other stuff happens here...
});

return 位单独工作正常,但在每次击键后将插入符号位置移回潜水的开始,这显然是不可取的。但是试图保持插入符号的位置(使用看到的一些代码 here)会在 JSHint 中抛出 Unreachable 'this' after 'return',因此实际上并没有在浏览器中做任何事情。有人可以在这里指出我正确的方向吗?

【问题讨论】:

  • 1.定义名为 resultHTML 的变量。 2.将您编辑的html存储在其中。 3. 执行 selectionRange 的东西。 4. 返回resultHTML。
  • 当我这样做时,我得到一个错误:TypeError: 'undefined' is not a function (evaluating 'this.setSelectionRange(start,end)')。不知道那里发生了什么。
  • setSelectionRange 是 HTMLInputElement 的一个函数。在您的代码中,this 指向其他内容。试试$(yourInputElement).setSelectionElement(...);(只是一个快速而肮脏的尝试......)。
  • 感谢您迄今为止的帮助,但我找不到有关该 setSelectionElement 方法的任何文档 - 您能指出我的文章或(甚至更好)某个工作示例吗?

标签: javascript jquery


【解决方案1】:

我总是倾向于将this 保留在变量中以避免范围问题。我也不太明白你为什么如此努力地将所有内容封装在匿名函数中。尝试更改您的代码如下:

$("#editor").on("keyup", ".content", function () {
    var target = this;
    var selection = window.getSelection();
    var range = selection.getRangeAt(0);
    var startOffset = range.startOffset;
    var endOffset = range.endOffset;
    var html = $(target).html();
    var newHtml = html.replace(/'\b/g, "\u2018") // opening single
    .replace(/\b'/g, "\u2019") // closing single
    .replace(/"\b/g, "\u201c") // opening double
    .replace(/\b"/g, "\u201d") // closing double
    .replace(/--/g, "\u2014") // em-dash
    .replace(/\b\u2018\b/g, "'"); // handle conjunctions
    var delta = html.length - newHtml.length;
    $(target).html(newHtml);

    var newRange = document.createRange();
    newRange.setStart(range.startContainer, startOffset - delta);
    newRange.setEnd(range.startContainer, endOffset - delta);
    selection.removeAllRanges();
    selection.addRange(newRange);

    // other stuff happens here...
});

我更正了代码,使其可以在 Chrome 下与 contenteditable 一起使用。将插入符号位置重置为开头的行为显然不会发生在 IE 中。所需知识位于: https://developer.mozilla.org/en-US/docs/Web/API/Selection

Edit2:我修复了“--”的问题并准备了一个小提琴。正如我测试的那样,在 Chrome 和 IE 中一切正常。 http://jsfiddle.net/mcoo/8oyn41b1/

【讨论】:

  • 谢谢,但正如@Doe Johnson 上面指出的那样,setSelectionRange 是 HTMLInputElement 的一个函数,因此不会真正适用于div。插入符号只是使用上面的代码不断返回到 div 的开头。我现在可能只是把这个放在“太难”的篮子里。
  • 哦,抱歉,我错过了您问题的内容可编辑方面。无论如何,您在哪个浏览器上收到这种行为?也许“其他东西”对插入符号位置有一些影响?
  • Mac 上的 Chrome 和 Safai 以及 Win 上的 Chrome(所以所有的 Webkit 浏览器 - 还没有在任何平台上尝试过 FF)。
  • 谢谢!它对我来说很有效......引号的替换在我的divs 之一中工作,但是在替换 em-dash 后插入符号会跳回到 div 的开头。而在第二个contenteditable div 中,它会在每次击键后跳回到开头。
  • 如果它有所作为,这就是我的 HTML 的样子:<div id="editor"> <div id="title" class="content" contenteditable="true"></div> <div id="body" class="content" contenteditable="true"></div> </div>
猜你喜欢
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 2017-12-06
  • 2010-10-14
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 2013-11-17
相关资源
最近更新 更多