将 Span 转换为 Input

7

我是一名开发Web应用程序的人,我有这样一个需求,每当用户点击中的文本时,我需要将其转换为输入框,并在失去焦点时将其转换回。因此,我在我的jsp页面中使用以下脚本。

JavaScript:

<script type="text/javascript">
function covertSpan(id){

    $('#'+id).click(function() {
        var input = $("<input>", { val: $(this).text(),
                                   type: "text" });
        $(this).replaceWith(input);
        input.select();   
    }); 

      $('input').live('blur', function () {
            var span=$("<span>", {text:$(this).val()});
            $(this).replaceWith(span);

      });         
}

JSP 代码:

<span id="loadNumId" onmouseover="javascript:covertSpan(this.id);">5566</span>

现在我的问题是,只有第一次点击 span 内的文本时,一切都正常。我的意思是,每当我点击 第一次 时,它就会转换为输入字段,再次 onblur 它会从输入字段转换回普通文本。但如果再试一次,它就不起作用了。上述脚本有什么问题吗?


还有一些jQuery插件可以实现“编辑即时生效”:http://stackoverflow.com/questions/708801/whats-the-best-edit-in-place-plugin-for-jquery - Stefan Profanter
5个回答

18

建议您将DOM结构更改为以下方式(请注意,.inputSwitch是共同的父元素,其中并排放置)

<div class="inputSwitch">
First Name: <span>John</span><input />
</div>
<div class="inputSwitch">
Last Name: <span>Doe</span><input />
</div>

那么我们可以这样编写我们的JS代码,它将支持在焦点选择所有内容以及通过Tab键切换到下一个/上一个span/input:

http://jsfiddle.net/x33gz6z9/
var $inputSwitches = $(".inputSwitch"),
  $inputs = $inputSwitches.find("input"),
  $spans = $inputSwitches.find("span");
$spans.on("click", function() {
  var $this = $(this);
  $this.hide().siblings("input").show().focus().select();
}).each( function() {
  var $this = $(this);
  $this.text($this.siblings("input").val());
});
$inputs.on("blur", function() {
  var $this = $(this);
  $this.hide().siblings("span").text($this.val()).show();
}).on('keydown', function(e) {
  if (e.which == 9) {
    e.preventDefault();
    if (e.shiftKey) {
      $(this).blur().parent().prevAll($inputSwitches).first().find($spans).click();
    } else {
      $(this).blur().parent().nextAll($inputSwitches).first().find($spans).click();
    }
  }
}).hide();

我现在有一个问题,更新了我的jQuery版本后,上面的代码不起作用了。 - Kishan_KP
什么版本?我刚在2.0和2.x(边缘)上运行它,它可以正常工作。发生了什么?控制台中有显示任何错误吗? - Smern

2

我知道你认为元素替换是一件好事,然而,我会使用提示框来获取文本。为什么呢?这样做更加简单,并且对用户来说也更美观。如果你想知道如何实现,我可以向你展示。

HTML:

<span class='editable'>foobar</span>

js:

$(function()
{
  $('span.editable').click(function()
  {
    var span = $(this);
    var text = span.text();

    var new_text = prompt("Change value", text);

    if (new_text != null)
      span.text(new_text);
  });
});

http://jsfiddle.net/qJxhV/1/


1
首先,您需要更改点击处理程序以使用live()。但请注意,live()已经被弃用了一段时间了。您应该在这两种情况下使用on()
其次,当您用span替换输入时,您没有给元素一个id。因此,该元素不再与您的点击处理程序的选择器匹配。
个人而言,我会采取完全不同(更简单)的方法。我会将span和输入都放在我的标记中并排显示。其中一个将被隐藏,而另一个将被显示。这将使您在尝试重新创建DOM元素时减少错误的机会,并提高性能,因为您不会不断地向DOM添加/删除元素。

因此,该元素不再与您的单击处理程序匹配选择器 - 哪个单击处理程序? covertSpan 仅调用一次,我看不到其他单击处理程序附加。 - a better oliver
不错的想法!我得试一下。 - Kishan_KP

0

我在代码中做了一点改动,使用这个输入类型时不能留空,它会返回其真实值。

 var switchToInput = function () {
        var $input = $("<input>", {
            val: $(this).text(),
            type: "text",
            rel : jQuery(this).text(),
        });
        $input.addClass("loadNum");
        $(this).replaceWith($input);
        $input.on("blur", switchToSpan);
        $input.select();
    };
    var switchToSpan = function () {
            if(jQuery(this).val()){
                        var $text = jQuery(this).val();
                } else {
                      var $text = jQuery(this).attr('rel');
                }
        var $span = $("<span>", {
            text: $text,
        });
        $span.addClass("loadNum");
        $(this).replaceWith($span);
        $span.on("click", switchToInput);
    }
    $(".loadNum").on("click", switchToInput);

jsFiddle:- https://jsfiddle.net/svsp3wqL/


0

通过略微修改两行代码,可以创建一个更通用的 smerny's excellent answer 版本,其中包含 id:

$input.attr("ID", "loadNum"); 变成 $input.attr("ID", $(this).attr("ID")); -- 这样,它只需获取当前的 id,并保持不变。

同样地, $span.attr("ID", "loadNum"); 变成 $span.attr("ID", $(this).attr("ID"));

这样就可以将函数应用于任何 div。添加两行类似的代码后,id 和 class 都可以正常工作。请参见 example


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接