0

I have this genealogical tree, starting with a user (below is the jsFiddle).

This user has 2 options (one working, the other one is not operative for the moment), one of them (+) opens a popUp to: add a "couple", add a "child" and add a "parent".

Adding a child creates a new child under the parent, with the same options.

For children and couples the code works perfectly, with the .on("click") method from jQuery, but when the "parent" option is selected, those options doesn't triggers the .on("click") method.

This genealogical tree is got from internet. An <ul> with <li> foreach element, and nested <ul> inside a <li> if this element has a child. So, if I add a parent, I wrap all the entire existing <ul> into a new <li> and this one into a new <ul>.

Code: jsFiddle

Hope you can help me to understand why the parent .on("click") is not triggering like the children.

0

3 Answers 3

4

Your binding is not correct, Change the line

$("li").on("click", ".anadir", function() {

to

$(".tree").on("click", ".anadir", function() {

Working Demo

Sign up to request clarification or add additional context in comments.

Comments

3

The problem is you are binding the click handler to the li element in .tree, but an a parent element is added you are creating a new li element which does not have the delegated click handler.

When you use event delegation targeting multiple elements you need to bind the handler to a common ancestor which is present in the dom when the handler is registered

$('.tree').on("click", ".anadir", function() {});

$(document).ready(function() {
  $('.tree').on("click", ".anadir", function() {
    //con
    $(".popUp").fadeIn();
    if ($(this).parent().parent().hasClass("top")) {
      $(".parentShow").show();
    } else {
      $(".parentShow").hide();
    }
    var id = $(this).parent().parent().attr("id");
    $("input[name='id']").val(id);
    console.log($("input[name='id']").val());
  });
  $(".popUp").click(function() {
    $(this).fadeOut();
  });
  $("#add").on("click", function() {
    //Obtain max id
    var max = 0;
    $("li").each(function() {
      if ($(this).attr("id") > max)
        max = $(this).attr("id");
    });
    max++;
    var type = $("input[name='add']:checked").val();
    var name = $("input[type='text']").val();
    var id = $("input[name='id']").val();
    console.log("id:" + id);

    if (type == "child") {
      if ($("#" + id).children("ul").length > 0) {
        console.log("a");
        $("#" + id).children("ul").append("<li id='" + max + "'><a href='#'><div class='user'>" + name + "</div><span class='couple'></span><div class='clear'></div><span class='anadir option'>+</span> <span class='restar option'>-</span></a></li>");
      } else {
        console.log("b");
        $("#" + id).append("<ul><li id='" + max + "'><a href='#'><div class='user'>" + name + "</div><span class='couple'></span><div class='clear'></div><span class='anadir option'>+</span> <span class='restar option'>-</span></a></li></ul>");
      }
    } else if (type == "couple") {
      $("#" + id + " a .couple").first().html("<div class='user'>" + name + "</div>");
    } else if (type == "parent") {
      $("#" + id).removeClass("top");
      $("#" + id).parent().wrap("<ul></ul>");
      $("#" + id).parent().wrap("<li id='" + max + "' class='top'></li>");
      $("#" + max).prepend("<a href='#'><div class='user'>" + name + "</div><span class='couple'></span><div class='clear'></div><span class='anadir option'>+</span><span class='restar option'>-</span></a>");
    }
    $(".popUp").fadeOut();
  });
  $(".popUp *").click(function(e) {
    e.stopPropagation();
  });
});
/*Now the CSS*/

* {
  margin: 0;
  padding: 0;
}
.tree ul {
  padding-top: 20px;
  position: relative;
}
.tree li {
  float: left;
  text-align: center;
  list-style-type: none;
  position: relative;
  padding: 20px 5px 0 5px;
}
/*We will use ::before and ::after to draw the connectors*/

.tree li::before,
.tree li::after {
  content: '';
  position: absolute;
  top: 0;
  right: 50%;
  border-top: 1px solid #ccc;
  width: 50%;
  height: 20px;
}
.tree li::after {
  right: auto;
  left: 50%;
  border-left: 1px solid #ccc;
}
/*We need to remove left-right connectors from elements without 
any siblings*/

.tree li:only-child::after,
.tree li:only-child::before {
  display: none;
}
/*Remove space from the top of single children*/

.tree li:only-child {
  padding-top: 0;
}
/*Remove left connector from first child and 
right connector from last child*/

.tree li:first-child::before,
.tree li:last-child::after {
  border: 0 none;
}
/*Adding back the vertical connector to the last nodes*/

.tree li:last-child::before {
  border-right: 1px solid #ccc;
  border-radius: 0 5px 0 0;
  -webkit-border-radius: 0 5px 0 0;
  -moz-border-radius: 0 5px 0 0;
}
.tree li:first-child::after {
  border-radius: 5px 0 0 0;
  -webkit-border-radius: 5px 0 0 0;
  -moz-border-radius: 5px 0 0 0;
}
/*Time to add downward connectors from parents*/

.tree ul ul::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  border-left: 1px solid #ccc;
  width: 0;
  height: 20px;
}
.tree li a {
  border: 1px solid #ccc;
  padding: 5px 10px;
  text-decoration: none;
  color: #666;
  font-family: arial, verdana, tahoma;
  font-size: 11px;
  display: inline-block;
  border-radius: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  transition: all 0.5s;
  -webkit-transition: all 0.5s;
  -moz-transition: all 0.5s;
}
/*Time for some hover effects*/

/*We will apply the hover effect the the lineage of the element also*/

.tree li a:hover,
.tree li a:hover+ul li a {
  background: #c8e4f8;
  color: #000;
  border: 1px solid #94a0b4;
}
/*Connector styles on hover*/

.tree li a:hover+ul li::after,
.tree li a:hover+ul li::before,
.tree li a:hover+ul::before,
.tree li a:hover+ul ul::before {
  border-color: #94a0b4;
}
/*Thats all. I hope you enjoyed it.
Thanks :)*/

.user {
  width: 50px;
  height: 50px;
  background: red;
  border: 1px solid #ccc;
  border-radius: 25px;
  margin: 10px;
  text-align: center;
  color: #fff;
  line-height: 50px;
  margin: 10px;
  display: block;
  float: left;
}
.clear {
  clear: both;
}
.start {
  background: #aaaaff;
}
.option {
  margin: 0 10px;
}
.popUp {
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, .5);
  position: absolute;
  top: 0;
  left: 0;
  display: none;
}
.popUpBox {
  width: 600px;
  height: auto;
  position: relative;
  top: 100px;
  margin: auto;
}
.boxTitle {
  background-color: #fff;
  border-bottom: 1px solid #ccc;
  padding: 10px;
}
.boxMessage {
  padding: 10px;
  background-color: #fff;
}
.add table {
  border-collapse: collapse;
  width: 100%;
}
.add table tr td {
  width: 50%;
  padding: 3px 10px;
  border: 1px solid #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="tree">
  <ul>
    <li id="0" class="top">
      <a href="#" class="start">
        <div class="user">Sergi</div>
        <span class="couple"></span>
        <div class="clear"></div>
        <span class="anadir option">+</span>
        <span class="restar option">-</span>
      </a>
    </li>
  </ul>
</div>
<div class="popUp">
  <div class="popUpBox">
    <h2 class="boxTitle">Tree options</h2>
    <div class="boxMessage">
      <div class="add">
        <b>Add</b>
        <table>
          <tbody>
            <tr>
              <td>
                <input type="radio" name="add" value="couple" checked="">Couple</td>
              <td>Name:
                <input type="text">
              </td>
            </tr>
            <tr>
              <td colspan="2">
                <input type="radio" name="add" value="child">Child</td>
            </tr>
            <tr class="parentShow">
              <td colspan="2">
                <input type="radio" name="add" value="parent">Parent</td>
            </tr>
            <tr>
              <input type="hidden" name="id" value="0">
              <td colspan="2" style="text-align: right;"><span><button id="add" style="padding: 3px 10px;">Add</button></span>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

2 Comments

thanks for explaining it! I will take that in mind next time! Thanks.
It was clear from a single line. I think, the code snippet is ok but will look much pretty if you hide the code snippet.
2

Check DEMO

$(document).ready(function() {
$(document).on("click", ".anadir", function() {
    $(".popUp").fadeIn();
    if($(this).parent().parent().hasClass("top")) {
        $(".parentShow").show();
    }
    else {
        $(".parentShow").hide();
    }
    var id = $(this).parent().parent().attr("id");
    $("input[name='id']").val(id);
    console.log($("input[name='id']").val());
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.