【问题标题】:Generic click-to-rename script in JavaScript (text to input/textbox)JavaScript 中的通用点击重命名脚本(文本到输入/文本框)
【发布时间】:2009-10-25 03:09:39
【问题描述】:

编写一个能够通过单击文本名称并输入新名称来重命名文件的小部件。我没有找到任何现成的解决方案,也许你可以指点我一个?

这是我结束的地方,但它不起作用:由于某种原因,只有最后一个输入框在改变,第一个和第二个没有被引用:

<span id="text_name_0">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_0" />
<input type="hidden" id="done_changing_0" value="Done"/>
<br/>
<span id="text_name_1">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_1" />
<input type="hidden" id="done_changing_1" value="Done"/>
<br/>
<span id="text_name_2">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_2" />
<input type="hidden" id="done_changing_2" value="Done"/>

<script type="text/javascript">

function TextChanger(id) {
    this.textNode = document.getElementById('text_name_' + id);
    this.textValue = this.textNode.firstChild.nodeValue;
    this.textboxNode = document.getElementById('name_changer_' + id);
    this.doneButton = document.getElementById('done_changing_' + id);
}   

TextChanger.prototype.change = function(node) {
          node.textboxNode.setAttribute('value', node.textValue);
          node.textNode.style.display = 'none';
          node.textboxNode.setAttribute('type','text');
          node.doneButton.setAttribute('type','button');
}   

TextChanger.prototype.changeBack = function(node) {
          node.textNode.firstChild.nodeValue = node.textboxNode.value;
          node.textNode.style.display = 'block';
          node.textboxNode.setAttribute('type', 'hidden');
          node.doneButton.setAttribute('type','hidden');
}

for (var i=0; i < 3; i++) {
        changer = new TextChanger(i);
        changer.textNode.addEventListener("click", function() {
            changer.change(changer);
        }, false);

        changer.doneButton.addEventListener("click", function() {
            changer.changeBack(changer);
        }, false);
}
</script>

谢谢。

【问题讨论】:

  • 接受一个答案是有礼貌的(点击检查)您也可以投票支持任何其他被证明有帮助或教会您一些东西的答案。

标签: javascript textbox input click


【解决方案1】:

这是一个经典的循环变量绑定问题。请参阅this question 进行一些讨论。

您的关闭无效,因为它关闭了循环内使用的changer 的副本,循环将更改该副本。要绑定它,您需要另一个闭包来复制当前版本的changer

function changebind(c) {
    return function() {
        c.change(c);
    };
}

for (var i=0; i<3; i++) {
    var changer= new TextChanger(i);
    changer.textNode.addEventListener('click', changebind(changer), false);

(您可能更愿意放弃 node 参数而只使用 this。)

在未来(ECMAScript 第五版),会有更快更有效的方式来表达这个:

for (var i=0; i<3; i++) {
    var changer= new TextChanger(i);
    changer.textNode.addEventListener('click', changer.change.bind(changer), false);
    changer.doneButton.addEventListener('click', changer.changeBack.bind(changer), false);
}

但与此同时,由于大多数浏览器尚不支持function.bind,您可以像这样破解它:

if (!Object.bind) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}

【讨论】:

    【解决方案2】:

    如果您不介意 jQuery 依赖项,我之前使用过 jquery-in-place-editor 来编辑字段。

    【讨论】:

      【解决方案3】:

      问题在于,当此处添加的侦听器函数触发时,它们包含对全局变量“changer”的引用。在他们触发循环时,循环已经完成,因此“changer”指向循环中的最后一项。

      此外,跨浏览器添加侦听器可能会很麻烦,使用 jQuery 或 YUI 之类的库更安全。这也将使您能够将对象传递给每个事件侦听器(以跨浏览器的方式),因此例如您可以这样做:

      for (var i=0; i < 3; i++) {
                      var changer = new TextChanger(i);
                      YAHOO.util.Event.addListener(changer.textNode, "click", changer.change, changer); 
                      ...
      

      【讨论】:

      • 谢谢 - 现在我明白了原因。 javascript 使用的是“by-ref”,而不是“by-value”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-16
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2019-06-04
      相关资源
      最近更新 更多