user1837363
user1837363

Reputation:

jQuery element.before() inserts incorrectly formatted element

Building a simple todo list (because we need another one of those). Using the jQuery.before() to insert a new item before a blank li at the end. The jQuery is below:

$('#blankLine').before('<li class="item">' +
    '<div class="todo-item">' +
        '<input type="checkbox">' +
        '<p contenteditable="true">' +
            '<span>a</span>' +
            'Walk the cat' +
            '<span>a</span>' +
        '</p>' 
    '</div>' +
    '<div class="mover">' +
        '<i class="fa fa-bars" aria-hidden="true"></i>' +
    '</div>' +
'</li>');

The HTML:

<li class="item">
    <div class="todo-item">
        <input type="checkbox">
        <p contenteditable="true">
            <span>a</span>
            Walk the cat
            <span>a</span>
        </p>
    </div>
    <div class="mover">
        <i class="fa fa-bars" aria-hidden="true"></i>
    </div>
</li>
<li id="blankLine"></li>

The relevant SCSS:

li {
    border-bottom: 1px solid #29AADD;
    height: 1.75em;
    padding-bottom: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .todo-item {
        width: 50%;
    }

    input {
        margin: 1px 4px 2px 10px;
    }
    p {
        margin: 0;
        margin-left: 12px;
        display: inline;
        height: 1em;
        padding-right: 2px;
        padding-left: 2px;
        width: 100%;

        //Bug in Firefox would insert a pair of <br> tags on the inside of 
        //<p contenteditable="true"> *** </p> just before the closing p tag
        br {
            display: none;
        }
    }
    span {
        padding: 0;
        margin: 0;
        color: #FDFD77;
    }
    .mover {
        margin-right: 3%;
        cursor: pointer;
    }
    i {
        padding: 0;
        margin: 0 !important;
    }
    &.new-item p{
        color: lighten($primary-text, 20%);
    }

    input[type=checkbox]:checked ~ p {
        text-decoration: line-through;
        color: lighten($primary-text, 10%);
    }
}

The jQuery adds the new element, but the p tag has a smaller width and appears closer to the checkbox. I have dug into the developer tools and the computed CSS is the same for the hardcoded li item and all it's descendants as the inserted li item and it's descendants.

Why is this doing this, and what can I do to fix it? (The link to the codepen: http://codepen.io/SethHerning/pen/851735ca813ac08a73f8c86d322421d3)

Upvotes: 2

Views: 68

Answers (1)

kukkuz
kukkuz

Reputation: 42352

Its due to the whitespaces in your markup.

Solution:

The easiest thing you can do here is to use <!-- --> between the elements to remove the whitespaces in the markup.

//Here starts the real fun!
/* Things to consider
	1) Entering new item (turn into regular and add new "Add")
	2) Moving items (will need 3rd party plugin)
	3) Saving items to local storage (what actions trigger save)
	4) Loading from local storage
*/

$(document).ready(function() {

  //Adding new item
  $('#addItem').click(function() {
    // alert("Pressed");
    // $('.new-item input p').val("");
    // $('.new-item input').removeAttr("disabled");
    $('#blankLine').before('<li class="item">' +
      '<div class="todo-item">' +
      '<input type="checkbox">' +
      '<p contenteditable="true">' +
      '<span>a</span>' +
      'Walk the cat' +
      '<span>a</span>' +
      '</p>' +
      '</div>' +
      '<div class="mover">' +
      '<i class="fa fa-bars" aria-hidden="true"></i>' +
      '</div>' +
      '</li>');
    // $('.new-item').prev().removeClass('new-item');
    return false;
  });
});
* {
  margin: 0;
  padding: 0;
}
body {
  background: #844E20;
  color: #000;
}
.notepad {
  width: 50vw;
  min-width: 300px;
  max-width: 600px;
  height: 90vh;
  margin: 5vh auto;
  padding: 0;
  background: #FDFD77;
  /* offset-x | offset-y | blur-radius | spread-radius | color */
  box-shadow: 0px 10px 10px 5px #222;
  position: relative;
}
.notepad #addItem {
  position: absolute;
  bottom: 0;
  right: 5px;
  font-size: 2em;
  cursor: pointer;
}
header {
  background: white;
  height: 7.5vh;
  border-bottom: 1px solid black;
}
header h3 {
  width: 75%;
  /* % of header, not vw of screen */
  margin: auto;
  padding: 1.5vh;
  text-align: center;
  font-size: 2em;
}
section {
  margin-top: 2vh;
}
section ul {
  width: 100%;
}
section li {
  border-bottom: 1px solid #29AADD;
  height: 1.75em;
  padding-bottom: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
section li .todo-item {
  width: 50%;
}
section li input {
  margin: 1px 4px 2px 10px;
}
section li p {
  margin: 0;
  margin-left: 2px;
  display: inline;
  height: 1em;
  padding-right: 2px;
  padding-left: 2px;
  width: 100% !important;
}
section li p br {
  display: none;
}
section li span {
  padding: 0;
  margin: 0;
  color: #FDFD77;
  display: inline-block;
}
section li .mover {
  margin-right: 3%;
  cursor: pointer;
}
section li i {
  padding: 0;
  margin: 0 !important;
}
section li.new-item p {
  color: #333333;
}
section li input[type=checkbox]:checked ~ p {
  text-decoration: line-through;
  color: #1a1a1a;
}
@media (max-height: 650px) {
  header h3 {
    font-size: 1.5em;
  }
}
@media (max-height: 400px) {
  header h3 {
    font-size: 1em;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="notepad">
  <header>
    <h3>My checklist</h3>
  </header>
  <section>
    <ul class="checklist">
      <li></li>
      <li class="item">
        <div class="todo-item">
          <input type="checkbox"><!--
          --><p contenteditable="true"><!--
            --><span>a</span><!--
            -->Walk the cat
            <span>a</span>
          </p>
        </div>
        <div class="mover">
          <i class="fa fa-bars" aria-hidden="true"></i>
        </div>
      </li>
      <li class="item">
        <div class="todo-item">
          <input type="checkbox"><!--
          --><p contenteditable="true"><!--
            --><span>a</span><!--
            -->Walk the cat
            <span>a</span>
          </p>
        </div>
        <div class="mover">
          <i class="fa fa-bars" aria-hidden="true"></i>
        </div>
      </li>
      <li id="blankLine"></li>
  </section>
  <div id="addItem">+</div>
</div>

Upvotes: 1

Related Questions