替换随机单词的最后一次出现

时间:2014-11-20 19:22:50

标签: javascript jquery html replace

我有一个像Emmet / ZenCoding一样的jQuery脚本,并且在TAB的{​​{1}}键的压力下将关键字扩展为一个片段。

当关键字只出现一次时,它可以正常工作,但我不知道如何只替换字符串中单词的最后一次出现。

这是一个将在textarea中输入的示例字符串:

textarea

在这种情况下,用户可以在第二个规则之后按Have a look at the rules : rules 键,脚本将获取数组中的相应值,以使用实际的规则链接替换该单词。它应该(在理论上)被替换为:

TAB

我的问题是我使用Have a look at the rules : http://website.com/rules.php 并且它将替换该单词的所有出现,这不是所需的行为。以下是该脚本的相关部分:

replace

首先获取textarea中的内容,将单词(rules)替换为相应的值(实际链接)。有没有办法只替换最后一次出现?它永远不会成为"规则",还有十几个未知长度的其他关键词。

TL; DR 如何用jQuery / Javascript替换单词的最后一次出现?

我正在考虑获得插入符号的当前位置并仅替换其左侧的单词,但是获得插入符号的位置似乎相当繁琐 - 我仍然不知道如何进行替换。 / p>

4 个答案:

答案 0 :(得分:1)

这可能会这样做,只要您的搜索字符串不包含任何正则表达式特殊字符:

var replaceLast = function(searchFor, replaceWith, str) {
    return str.replace(
        new RegExp("^(.*)" + searchFor + "(.*?)$"), 
        function(_, before, after) {return before + replaceWith + after;}
    );
};

replaceLast("rules", "http://website.com/rules.php", 
            "Have a look at the rules : rules", "rules");
//=> "Have a look at the rules : http://website.com/rules.php"

如果此函数已传递给某个curry函数,那么您可以通过

创建一个函数,例如updateRules
var updateRules = replaceLast("rules", "http://website.com/rules.php");
// ... later
updateRules("Have a look at the rules : rules", "rules");
//=> "Have a look at the rules : http://website.com/rules.php"

但原始功能可能就是您所需要的。

答案 1 :(得分:1)

这是我使用contenteditable字段提出的(仅测试过webkit)。

虽然可能效率低下,但确实做了一些事情:

  • 使用生活在对象中的相关代码段替换word
  • 仅替换您的插入符号中的当前单词
  • 在完成标签后将光标设置到行尾

尝试输入"等等等等等等等等。并在"规则"之后点击标签。尝试使用多个"规则"在字符串中。



var content = document.getElementById('content')

content.addEventListener('keydown', function (event) {

    var _this      = this,
        text       = this.innerHTML;

    if ( event.keyCode == 9 ) {
        event.preventDefault()

        var sel         = window.getSelection(),
            currentWord = getWord(),
            val         = sel.anchorNode.nodeValue,
            snippet     = tabComplete(currentWord),
            range       = sel.getRangeAt(0)

        var selArray    = sel.anchorNode.nodeValue.split(' ')

        if ( snippet !== undefined ) {
            var currentWordPosition = [ (range.endOffset - currentWord.length), range.endOffset ]

            var newText = text.splice(currentWordPosition[0], currentWordPosition[1], ' '+snippet)

            _this.innerHTML = newText;

            sel.collapse(_this.firstChild, sel.anchorNode.nodeValue.length)
        }
    }
  
})

var snippets = {
    'rules' : 'http://website.com/rules.php',
    'faq' : 'http://website.com/faq.php'
}

function tabComplete(string) {

    if ( typeof string !== 'string' ) { return false; }

    var snippetKeys = Object.keys(snippets)

    for ( var i=0; i<snippetKeys.length; i++ ) {
        if ( snippets[string] ) {
            return snippets[string]
        }
    }
}

function getWord() {
    var range = window.getSelection().getRangeAt(0);
    if ( range.collapsed ) {
        text = range.startContainer.textContent.substring(0, range.startOffset+1);
        return text.split(/\b/g).pop();
    }
    return '';
}

String.prototype.splice = function(start, length, replacement) {
    return this.substr(0,start)+replacement+this.substr(start+length);
}
&#13;
#content {
  width:350px;
  height:150px;
  background-color: #333;
  color: white;
  font-family: sans-serif;
  padding:10px;
}
&#13;
<div id="content" contenteditable></div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

使用正则表达式并仅匹配内容字符串的结尾。

/yourWord$/
如果它位于字符串的最后,

将匹配你的字符

答案 3 :(得分:0)

稍微调整正则表达式:

var content = $(this).val();
content = content.replace(lastWord+'.*?$', insertSnippets[lastWord]);
$(this).val(content);