【问题标题】:Turn text element into input field type text when clicked and change back to text when clicked away单击时将文本元素转换为输入字段类型文本,并在单击离开时更改回文本
【发布时间】:2015-10-21 19:38:38
【问题描述】:

我正在尝试创建一个字段即时更改的表单。

从简单的文本开始,当有人点击此文本时,它会转移到可编辑的文本输入字段。当有人点击离开时,它会变回不可编辑的文本。

我试了一下,但它似乎不能正常工作。在前几次点击时工作正常,但随后它丢失了 inputId 并混合了按钮。

这里是html

<p id="firstElement" onclick="turnTextIntoInputField('firstElement');">First Element</p>
<p id="secondElement" onclick="turnTextIntoInputField('secondElement');">Second Element</p>

这里是 JavaScript(使用 jQuery)。

我是 JavaScript 新手,所以它可能不是最优质的代码...

function turnTextIntoInputField(inputId) 
{  
    console.log(inputId);
    inputIdWithHash = "#"+inputId;
    elementValue = $(inputIdWithHash).text();
    $(inputIdWithHash).replaceWith('<input name="test" id="'+inputId+'" type="text" value="'+elementValue+'">');

    $(document).click(function(event) { 
        if(!$(event.target).closest(inputIdWithHash).length) {
            $(inputIdWithHash).replaceWith('<p id="'+inputId+'" onclick="turnTextIntoInputField(\''+inputId+'\')">'+elementValue+'</p>');
        }      

    });
}

这是小提琴https://jsfiddle.net/7jz510hg/的实时示例

我会很感激任何帮助,因为它让我头疼......

【问题讨论】:

标签: javascript jquery html


【解决方案1】:

首先,您不需要在 html 本身中使用 onclick

您可能会采取另一种方法:

/**
  We're defining the event on the `body` element, 
  because we know the `body` is not going away.
  Second argument makes sure the callback only fires when 
  the `click` event happens only on elements marked as `data-editable`
*/
$('body').on('click', '[data-editable]', function(){
  
  var $el = $(this);
              
  var $input = $('<input/>').val( $el.text() );
  $el.replaceWith( $input );
  
  var save = function(){
    var $p = $('<p data-editable />').text( $input.val() );
    $input.replaceWith( $p );
  };
  
  /**
    We're defining the callback with `one`, because we know that
    the element will be gone just after that, and we don't want 
    any callbacks leftovers take memory. 
    Next time `p` turns into `input` this single callback 
    will be applied again.
  */
  $input.one('blur', save).focus();
  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p data-editable>First Element</p>
  
<p data-editable>Second Element</p>
  
<p>Not editable</p>

【讨论】:

  • 如果我今天还有票,我会投票给你。它比我的答案更好。虽然老实说,我并没有试图重塑他正在做的事情,只是解决他遇到的问题并告诉他为什么会发生。
  • @Yura 这个答案也解决了我的问题。谢谢你们,你们很有帮助
  • 是的,但只能接受一个答案!不过不用担心,我不介意你换了答案,Yura 应得的。他的回答更优雅。我只是想向您展示您编写的代码有什么问题以及为什么它不起作用。生活仍在继续。 =]
  • @AtheistP3ace 你的回答也很棒,给了我很好的教训:)
  • @AtheistP3ace,我也会支持你的答案,让你的一天更美好:)
【解决方案2】:

小提琴:https://jsfiddle.net/7jz510hg/1/

问题在于没有用 var 定义 inputIdWithHash 和 elementValue 变量,它们变成了全局变量。

var inputIdWithHash
var elementValue

然后,由于它们具有全局范围,因此它们的旧值可用于文档单击处理程序。您希望它们在该 turnTextIntoInputField 函数的本地范围内。

还有一个更新维护值:https://jsfiddle.net/7jz510hg/2/

旁注,您使用的是 jQuery 1.6,所以我不得不使用 unbind 函数而不是 off。

更新小提琴:https://jsfiddle.net/7jz510hg/3/

这使用最新的 jquery,事件命名空间,因此我们可以将多个单击事件附加到文档,从而允许我们在字段之间单击而不会丢失任何内容。如果您直接单击字段而不是单击字段,单击文档,单击字段,则前面的小提琴会搞砸。

【讨论】:

  • 当我点击离开时,文本恢复到原来的值。
  • 是的,对不起,我只是在看他所说的问题,他正在失去并混淆它们。我将更新小提琴以处理值。一秒。
  • @AtheistP3ace 谢谢你的工作就像一个魅力!正是我所需要的 :) 如果您能更新您的小提琴,使值不会恢复到原始值,我将不胜感激。
  • @zachu 更新答案
  • 如果使用H2而不是P标签怎么办? @无神论者P3ace
【解决方案3】:

如果有人需要,我将 Yura 的 answer 从 JQuery 移植到 Vanilla JavaScript。这也适用于 p、h1、h2、span 等:

function editData(e) {
  const el = e.target;
  const input = document.createElement("input");
  input.setAttribute("value", el.textContent);
  el.replaceWith(input);

  const save = function() {
    const previous = document.createElement(el.tagName.toLowerCase());
    previous.onclick = editData;
    previous.textContent = input.value;
    input.replaceWith(previous);
  };

  /**
    We're defining the callback with `once`, because we know that
    the element will be gone just after that, and we don't want 
    any callbacks leftovers take memory. 
    Next time `p` turns into `input` this single callback 
    will be applied again.
  */
  input.addEventListener('blur', save, {
    once: true,
  });
  input.focus();
}

for (const child of document.querySelectorAll('[data-editable]')) {
  child.onclick = editData;
}
<h1 data-editable>First h1</h1>

<p data-editable>First Element</p>
  
<p data-editable>Second Element</p>
  
<p>Not editable</p>

相关:

【讨论】:

    【解决方案4】:

    我建议,不要把这复杂化。我使用简单的隐藏和显示方法将文本更改为输入字段。这很容易实现和理解。

     $('#editable').on('click',function(){
         var groupname = $("#editable").html();
         $("#editable").css({'display':"none"});
         $("#inputgroupname").css({'display':'block'});
         $("#inputgroupname").focus();
          $("#inputgroupname").val(groupname);
    });
    
    $("#inputgroupname").focusout(function(){
       $('#editable').html($("#inputgroupname").val());
      $("#inputgroupname").css({'display':'none'});
      $("#editable").css({'display':"block","margin-top":"2px"});
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <h3 class="box-title" style="margin-top:2px; margin-left:5px;" id="editable">Hello</h3>
     <input type="text"  id="inputgroupname" style="display:none;">

    【讨论】:

      【解决方案5】:

      试试这个

      $('#tbl').on('click','.editable',function() {
      
        var t = $(this);          
        var input = $('<input>').attr('class', 'savable').val( t.text() );
        t.replaceWith( input ); 
        input.focus();
      
      });
      
      $('#tbl').on('blur','.savable',function() {
      
        var input = $(this);      
        var t = $('<span>').attr('class', 'editable').text( input.val() );
        input.replaceWith( t ); 
      
      });
      

      http://jsfiddle.net/yp8bt6s0/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-11
        • 1970-01-01
        • 2021-04-29
        相关资源
        最近更新 更多