Michael Schwartz
Michael Schwartz

Reputation: 8425

Change Elements HTML but Ignore Last Child

With the way I have my HTML marked up....

<textarea></textarea>
<div class="body">

  <div class="content">don't change this</div>
</div>

Is it possible to change the html inside of .body without changing the html inside of .content?

EDIT:

I'm working on my code editor and my <script> tag in this case is replaced with .content, and <body> tag is replaced with .body.

The .before API seems to be the best solution for my case except if only 3 characters are added (ex. lol). The result in .body is (ex. lolollol)

$('textarea').keyup(function() {
  $('.content').before(this.value)
  return false
}).trigger('keyup')
textarea {
  width: 98%;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<div class="body">
  
  <div class="content">don't change this</div>
</div>

Upvotes: 2

Views: 73

Answers (4)

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

This is tricky, because .body may contain text nodes.

jQuery's contents() method helps :

$('textarea').keyup(function() {
  $('.body')
    .contents()                             //get both text nodes and element nodes
    .each(function() {
      if(this.className !== 'content') {
        this.nodeValue= this.innerHTML= ''; //nodeValue needed for text nodes, 
                                            //innerHTML for element nodes
      }
    });
  
  $('.content').before(this.value);
}).trigger('keyup');
textarea {
  width: 98%;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea>
  <ol>
    <li>test data here</li>
  </ol>
</textarea>
<div class="body">
  
  <div class="content">don't change this</div>
</div>

Upvotes: 4

zer00ne
zer00ne

Reputation: 43910

Keep HTML, CSS, and JS separate. See Snippet.

SNIPPET

$(".html").keyup(function() {
  $(".body").html(this.value)
}).trigger("keyup")
$(".css").keyup(function() {
  $(".style").html(this.value)
}).trigger("keyup")
$(".js").keyup(function() {
  $(".script").html(this.value)
}).trigger("keyup")
textarea {
  width: 98%;
  height: 100px;
}
.tag {
  font: 700 16px/1.45 'Consolas';
  color: grey;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<fieldset>
<legend>HTML</legend>
<textarea class="edit html">

</textarea>
</fieldset>

<fieldset>
<legend>CSS</legend>
<textarea class="edit css">
  
</textarea>
</fieldset>

<fieldset>
<legend>JavaScript</legend>
<textarea class="edit js">
  
</textarea>
</fieldset>

<hr/>

<section class="printer">
  
<div class="tag">&lt;html&gt;</div>
<div class="tag">&lt;head&gt;</div>
<div class="tag">&lt;style&gt;</div>
  
<div class="print style">
  
</div>
  
<div class="tag">&lt;/style&gt;</div>
<div class="tag">&lt;/head&gt;</div>
<div class="tag">&lt;body&gt;</div>
  
<div class="print body">
 
</div>

<div class="tag">&lt;script&gt;</div>
  
<div class="print script">
  
</div>
  
<div class="tag">&lt;/script&gt;</div>
<div class="tag">&lt;/body&gt;</div>
<div class="tag">&lt;/html&gt;</div>
</section>

Upvotes: 0

Daniel
Daniel

Reputation: 1466

you can append into $contentrather than changing the entire html

$('textarea').keyup(function(){
 $('.body').html(this.value).append($content)
}).trigger('keyup');

fiddle : https://jsfiddle.net/atg5m6ym/3320/

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337580

One workaround would be to get the reference to the .content element and append() it back in to the .body element after re-setting the html(). Try this:

$("textarea").keyup(function() {
  var $content = $('.content');
  $(".body").html(this.value).append($content);
}).trigger("keyup")
textarea {
  width: 98%;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<div class="body">
  <div class="content">don't change this</div>
</div>

Upvotes: 3

Related Questions