3

I am very ashamed to post this question but I have not managed to get use of unwrap or replaceWith methods in Jquery for that need.

My problem is simple : I need to remove some nodes (jquery selectors) of an html code without losing the children of these nodes.

Here is a Jsfiddle that demonstrate the result of my unsightly code used to reach my goal https://jsfiddle.net/uddaeh1u/15/ (yes it's works...)

// 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;
    }
});

Could you find me a really better code (with unwrap method) ?

Thank you a lot :)

ikodev
  • 49
  • 8

4 Answers4

1

If your intention is to only remove span.atwho-inserted without its children and the rest of the DOM remains the same, you can do so by:

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

First, select the elements with class .atwho-inserted, then find their respective first-child and perform unwrap.

unwrap removes the selector immediate parent wrapper and leaves behind the children.

And you are good to go!

n4m31ess_c0d3r
  • 3,028
  • 5
  • 26
  • 35
  • It seems a nice solution however in my case I work on a variable that contains the html code. unwrap() only returns the unwrapped jquery objects but not the whole code sanitized. – ikodev Nov 10 '16 at 12:13
  • since i compared your result and mine, they are the same except for the `

    ` tag i already mentioned in the question comment.

    – n4m31ess_c0d3r Nov 10 '16 at 12:34
  • Sorry, here is new jsFiddle with your solution :) https://jsfiddle.net/uddaeh1u/18/ I just discover the "update" button there... – ikodev Nov 10 '16 at 12:44
1

I think this one would please you. Notice modification of var 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>
arhak
  • 2,488
  • 1
  • 24
  • 38
  • Thank you but can you try to work with $(content) that contains the whole code. Indeed, it works well if I only use the jquery selector $('.atwho-inserted') that point on the DOM however I need to start from a recovered content stored in that variable. And here is my problem... – ikodev Nov 10 '16 at 13:01
  • Your code snippet keep the .atwho-inserted elements – ikodev Nov 10 '16 at 13:05
  • 1
    Great that works (I made a mistake) ! https://jsfiddle.net/uddaeh1u/23/ – ikodev Nov 10 '16 at 13:08
  • not sure what you meant... in that last fiddle I see the exact same outcome in `result` as in `tmpContent` (which BTW does not use `:first-child` as states description in 3rd case) – arhak Nov 10 '16 at 13:24
  • 1
    ok, now I saw it. Change to this `var result = tmpContent[0].outerHTML;` and you won't loos that outer `

    `

    – arhak Nov 10 '16 at 13:32
0

basically outerHTML is what you want to replace with innerHTML (unwrap) check 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>
arhak
  • 2,488
  • 1
  • 24
  • 38
  • Thank you ! However I havn't find the way to use this process directly on my variable "content". Unwrap() return the unwrapped Object jQuery or apply directly on the Dom. example of use : var content = $(messageContent).summernote('code'); $(content).find('.atwho-inserted').each(function() { this.outerHTML = $(this).html(); }); console.log($(content)); – ikodev Nov 10 '16 at 12:16
  • Sorry...i haven't found the way of publishing code in a comment here... – ikodev Nov 10 '16 at 12:28
  • for inline code use back-ticks `` and `there you go` – arhak Nov 10 '16 at 12:34
0

Here is another JsFiddle where i added the unwrap() solution https://jsfiddle.net/uddaeh1u/21/

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

I think the problem is that unwrap() only returns the jquery Objects unwrapped and can only apply on the DOM (not from a variable treated as a Dom Object).

ikodev
  • 49
  • 8
  • You haven't modified the value of `content` after initialising, so it is still `$('.start').html()` – n4m31ess_c0d3r Nov 10 '16 at 12:59
  • comment first line of second solution, add this line at the last `$('.result2').find('.atwho-inserted').children(':first-child').unwrap();` – n4m31ess_c0d3r Nov 10 '16 at 13:04
  • `$(content)` didn't work since you started with an jquery object(see its value), what i'm doing is directly manipulating the DOM (no need to store the value) – n4m31ess_c0d3r Nov 10 '16 at 13:06
  • I understand your work of course but I must not change the DOM. How can I store the result of your code `$('.result2').find('.atwho-inserted').children(':first-child').unwrap();` ?? – ikodev Nov 10 '16 at 13:19
  • Thing is : My wysiwyg with some other plugins generate a html code that I must change *before* sending it to the server. But I must not change the Dom directly, so I have to work on a copy. – ikodev Nov 10 '16 at 13:24