jQuery删除节点并保留子元素

3

很抱歉我要提出这个问题,但是我没有成功地使用Jquery中的unwrap或replaceWith方法。

我的问题很简单:我需要删除一些HTML代码中的节点(jquery选择器),同时保留这些节点的子元素。

这里有一个Jsfiddle演示了我难看的代码所达到的目标https://jsfiddle.net/uddaeh1u/15/ (是的它可以工作...)

// var content : the html source code of the wysiwyg

var result = '';
$(content).contents().each(function(){
    var addContent = '';
    // textNode
    if(this.nodeType == 3) {
        // Text Node
        result+= $(this).text();
    } else if(this.nodeType == 1 && $(this).hasClass('atwho-inserted')) {
        // if is an Object Node with the target class
        // I only keep it's contents (means that ".atwho-inserted" is not kept)
        result+= $(this).html();
    } else {
        // in any other case I keep it entirely
        result+= this.outerHTML;
    }
});

你能帮我找到一份更好的代码(包含unwrap方法)吗?

非常感谢你 :)


我注意到你在JSFiddle中运行了两个不同版本的Bootstrap CSS。 - Miquel Al. Vicens
在你的结果代码中,<p>也被移除了。这是预期的吗? - n4m31ess_c0d3r
@aManHasNoName 不,不是那样的...好吧,看起来像是另一个问题! - ikodev
谢谢 @MiquelAl.Vicens... 这是我的第一个 JsFiddle ;) - ikodev
4个回答

1
如果您的意图仅是删除 span.atwho-inserted 而不包括其子元素,同时保留其余DOM结构不变,您可以通过以下方式实现:
$('.start .atwho-inserted').children(':first-child').unwrap();

首先,选择具有类.atwho-inserted的元素,然后找到它们各自的第一个子元素并执行unwrapunwrap会删除选择器的直接父包装器,并留下其子元素。
这样你就可以开始了!

这似乎是一个不错的解决方案,但在我的情况下,我处理包含HTML代码的变量。unwrap()仅返回已解除包装的jQuery对象,而未对整个代码进行清理。 - ikodev
自从我比较了你的结果和我的结果,除了我在问题评论中提到的<p>标签之外,它们是一样的。 - n4m31ess_c0d3r
抱歉,这是包含您解决方案的新jsFiddle链接: https://jsfiddle.net/uddaeh1u/18/ 我刚刚发现了那里的“更新”按钮... - ikodev

1

我认为这个会让你满意。注意变量tmp的修改。

$(document).ready(function(){
  var content = $('.start').html();
  $('.startCode code').text(content);
  
  var tmp = $(content);
  $('.atwho-inserted', tmp).children().unwrap();
  var result = tmp[0].outerHTML; // or tmp.html(); but would lose the outermost tag
  
  $('.result').html(result);
  $('.resultCode').text(result);
});
body{
  padding:10px;
}
.atwho-inserted{
  background-color:red;
}
pre code, .wrap{
  white-space: pre-line;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div class="container">
  <div class="row">
    <div class="col-xs-6">
      <div class="well">All selectors ".atwho-inserted" are in "background-color:red" and have to be removed without losing its children.</div>
      <hr/>
      <div class="start">
        <p>
          <span class="atwho-inserted" data-atwho-at-query="@fac" contenteditable="false">
            <span class="user_mention" data-identifier="8930">@facticeuserr</span>
          </span>
          <br /> some lorem ipsum text
          <span class="atwho-inserted" data-atwho-at-query="#acc" contenteditable="false">
            <span class="tag_mention" data-identifier="484">#accessibilité</span>
          </span>
          <br>
          <img src="http://lorempixel.com/100/100/" data-filename="3">
          <br />
          <b>hello</b>
          <br>
          <span class="atwho-inserted" data-atwho-at-query="#acc" contenteditable="false">
            <span class="tag_mention" data-identifier="653">#Accompagnement</span>
          </span>
        </p>
      </div>
      <pre class="startCode"><code></code></pre>
    </div>
    <hr/>
    <div class="col-xs-6">    
      <div class="well">Here the result<br /> it's works but code is not optimized</div>
      <hr/>
      <div class="result"></div>
      <pre class="resultCode"><code></code></pre>
    </div>
  </div>
</div>


谢谢,但你能否尝试使用包含整个代码的$(content)进行操作? 实际上,如果我只使用指向DOM的jQuery选择器$('.atwho-inserted'),它可以很好地工作,但是我需要从存储在该变量中的恢复内容开始。这就是我的问题所在... - ikodev
你的代码片段保留了.atwho-inserted元素。 - ikodev
1
太好了,它可以工作了(我犯了一个错误)!https://jsfiddle.net/uddaeh1u/23/ - ikodev
我不确定你的意思……在上一个 fiddle 中,我看到 resulttmpContent 的结果完全相同(顺便说一句,第三种情况中的状态描述并未使用 :first-child)。 - arhak
1
好的,现在我看到了。将其更改为 var result = tmpContent[0].outerHTML;,你就不会失去那个外部的 <p> - arhak

0

基本上,outerHTML 是你想要用 innerHTML (解包) 替换的内容。 请查看 https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML#Browser_compatibility

$('#trigger').click(function() {
  $(this).hide();
  $('.atwho-inserted').each(function() {
    this.outerHTML = $(this).html();
  });
});
body{
  padding:10px;
}

.atwho-inserted{
  background-color:red;
}

pre code, .wrap{
  white-space: pre-line;
}

#trigger {
  font-size: 1.5em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button id="trigger">Click to trigger edition</button>

<div class="container">
  <div class="row">
    <div class="col-xs-6">
      <div class="well">All selectors ".atwho-inserted" are in "background-color:red" and have to be removed without losing its children.</div>
      <div class="start">
        <p>
          <span class="atwho-inserted" data-atwho-at-query="@fac" contenteditable="false">
            <span class="user_mention" data-identifier="8930">@facticeuserr</span>
          </span>
          <br /> some lorem ipsum text
          <span class="atwho-inserted" data-atwho-at-query="#acc" contenteditable="false">
            <span class="tag_mention" data-identifier="484">#accessibilité</span>
          </span>
          <br>
          <img src="http://lorempixel.com/100/100/" data-filename="3">
          <br />
          <b>hello</b>
          <br>
          <span class="atwho-inserted" data-atwho-at-query="#acc" contenteditable="false">
            <span class="tag_mention" data-identifier="653">#Accompagnement</span>
          </span>
        </p>
      </div>
      <pre class="startCode"><code></code></pre>
    </div>
    <div class="col-xs-6">    
      <div class="well">Here the result<br /> it's works but code is not optimized</div>
      <div class="result"></div>
      <pre class="resultCode"><code></code></pre>
    </div>
  </div>
</div>


谢谢!然而,我还没有找到直接在我的变量"content"上使用这个过程的方法。Unwrap()返回解包后的jQuery对象,或者直接应用于Dom。使用示例: var content = $(messageContent).summernote('code'); $(content).find('.atwho-inserted').each(function() { this.outerHTML = $(this).html(); }); console.log($(content)); - ikodev
抱歉...我还没有找到在这里以评论的方式发布代码的方法... - ikodev
对于内联代码,请使用反引号``和there you go - arhak

0

这里是另一个 JsFiddle,我添加了 unwrap() 解决方案 https://jsfiddle.net/uddaeh1u/21/

$(content).find('.atwho-inserted').children(':first-child').unwrap();

我认为问题在于unwrap()仅返回解包的jQuery对象,并且只能应用于DOM(而不能从变量作为DOM对象处理)。


你在初始化后没有修改 content 的值,所以它仍然是 $('.start').html() - n4m31ess_c0d3r
在第二个解决方案的第一行添加注释,并将此行添加到最后 $('.result2').find('.atwho-inserted').children(':first-child').unwrap(); - n4m31ess_c0d3r
$(content)自从你使用了一个jQuery对象(查看其值)就无法工作,我所做的是直接操作DOM(不需要存储值)。 - n4m31ess_c0d3r
我当然理解你的工作,但我不能更改DOM。我该如何存储您的代码 $('.result2').find('.atwho-inserted').children(':first-child').unwrap(); 的结果? - ikodev
事情是:我的所见即所得编辑器与其他插件一起生成了一个 HTML 代码,我必须在将其发送到服务器之前进行更改。但我不必直接更改 Dom,所以我必须在副本上进行操作。 - ikodev

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